[yocto] =?a?q?=5BPATCH=201/2=5D=20yocto/emgd=3A=20emgd=201=2E14=20driver?=

nitin.a.kamble at intel.com nitin.a.kamble at intel.com
Mon Jul 16 07:22:24 PDT 2012


From: Nitin A Kamble <nitin.a.kamble at intel.com>

The starting-point code that subsequent patches will modify.  This is
a straight copy of the code in the emgd 1.14 emgd driver, specifically
IEMGD_HEAD_Linux/common/drm/emgd_drm.tgz from
LIN_IEMGD_1_14_GOLD_2443.tgz, the 'Linux Tar Ball' release downloaded
from http://edc.intel.com/Software/Downloads/EMGD/.

Signed-off-by: Nitin A Kamble <nitin.a.kamble at intel.com>
Signed-off-by: Tom Zanussi <tom.zanussi at intel.com>
---
 drivers/gpu/drm/emgd/Makefile                      |  332 ++
 drivers/gpu/drm/emgd/emgd/cfg/config.h             |  113 +
 drivers/gpu/drm/emgd/emgd/cfg/config_default.h     |  199 +
 drivers/gpu/drm/emgd/emgd/cfg/config_helper.c      |  244 ++
 .../gpu/drm/emgd/emgd/core/init/cmn/igd_global.c   |   34 +
 drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_init.c |  918 +++++
 .../drm/emgd/emgd/core/init/cmn/init_dispatch.h    |   65 +
 drivers/gpu/drm/emgd/emgd/core/init/plb/init_plb.c |  458 +++
 .../drm/emgd/emgd/core/init/plb/micro_init_plb.c   |  631 ++++
 drivers/gpu/drm/emgd/emgd/core/init/tnc/init_tnc.c |  621 ++++
 .../drm/emgd/emgd/core/init/tnc/micro_init_tnc.c   |  998 +++++
 drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp.c    | 2366 ++++++++++++
 .../drm/emgd/emgd/display/dsp/cmn/dsp_dispatch.h   |   64 +
 .../gpu/drm/emgd/emgd/display/dsp/plb/dsp_plb.c    |  709 ++++
 .../gpu/drm/emgd/emgd/display/dsp/tnc/dsp_tnc.c    |  542 +++
 .../gpu/drm/emgd/emgd/display/mode/cmn/igd_mode.c  | 2340 ++++++++++++
 drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.c | 1347 +++++++
 drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.h |   59 +
 .../drm/emgd/emgd/display/mode/cmn/micro_mode.c    | 1767 +++++++++
 .../drm/emgd/emgd/display/mode/cmn/mode_dispatch.h |  390 ++
 .../gpu/drm/emgd/emgd/display/mode/cmn/vga_mode.c  | 1467 ++++++++
 .../drm/emgd/emgd/display/mode/plb/clocks_plb.c    |  711 ++++
 .../drm/emgd/emgd/display/mode/plb/kms_mode_plb.c  | 1102 ++++++
 .../emgd/emgd/display/mode/plb/micro_mode_plb.c    | 1378 +++++++
 .../gpu/drm/emgd/emgd/display/mode/plb/mode_plb.c  | 1946 ++++++++++
 .../gpu/drm/emgd/emgd/display/mode/plb/mode_plb.h  |   47 +
 .../drm/emgd/emgd/display/mode/tnc/clocks_tnc.c    | 1184 ++++++
 .../drm/emgd/emgd/display/mode/tnc/kms_mode_tnc.c  | 1746 +++++++++
 .../emgd/emgd/display/mode/tnc/micro_mode_tnc.c    | 2646 +++++++++++++
 .../gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.c  | 2074 +++++++++++
 .../gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.h  |   52 +
 drivers/gpu/drm/emgd/emgd/display/pd/cmn/pd.c      |  516 +++
 .../gpu/drm/emgd/emgd/display/pi/cmn/displayid.c   | 1109 ++++++
 drivers/gpu/drm/emgd/emgd/display/pi/cmn/edid.c    | 1187 ++++++
 .../drm/emgd/emgd/display/pi/cmn/i2c_dispatch.h    |   78 +
 drivers/gpu/drm/emgd/emgd/display/pi/cmn/igd_pi.c  |  260 ++
 .../gpu/drm/emgd/emgd/display/pi/cmn/mode_table.c  | 2545 +++++++++++++
 .../gpu/drm/emgd/emgd/display/pi/cmn/pd_init_all.c |  215 ++
 drivers/gpu/drm/emgd/emgd/display/pi/cmn/pi.c      | 1919 ++++++++++
 drivers/gpu/drm/emgd/emgd/display/pi/plb/i2c_plb.c |  943 +++++
 .../drm/emgd/emgd/display/pi/tnc/i2c_bitbash_tnc.c |  599 +++
 .../drm/emgd/emgd/display/pi/tnc/i2c_gmbus_tnc.c   |  929 +++++
 drivers/gpu/drm/emgd/emgd/drm/drm_emgd_private.h   |  176 +
 drivers/gpu/drm/emgd/emgd/drm/emgd_connector.c     |  512 +++
 drivers/gpu/drm/emgd/emgd/drm/emgd_crtc.c          |  997 +++++
 drivers/gpu/drm/emgd/emgd/drm/emgd_drv.c           | 2472 +++++++++++++
 drivers/gpu/drm/emgd/emgd/drm/emgd_drv.h           |  209 ++
 drivers/gpu/drm/emgd/emgd/drm/emgd_encoder.c       |  477 +++
 drivers/gpu/drm/emgd/emgd/drm/emgd_fb.c            | 1413 +++++++
 drivers/gpu/drm/emgd/emgd/drm/emgd_fbcon.c         |  805 ++++
 drivers/gpu/drm/emgd/emgd/drm/emgd_interface.c     | 2730 ++++++++++++++
 drivers/gpu/drm/emgd/emgd/drm/emgd_mmap.c          |  186 +
 drivers/gpu/drm/emgd/emgd/drm/emgd_test_pvrsrv.c   | 1365 +++++++
 drivers/gpu/drm/emgd/emgd/drm/image_data.h         |   33 +
 drivers/gpu/drm/emgd/emgd/drm/splash_screen.c      | 2221 +++++++++++
 drivers/gpu/drm/emgd/emgd/drm/splash_screen.h      |  280 ++
 drivers/gpu/drm/emgd/emgd/drm/user_config.c        |  252 ++
 drivers/gpu/drm/emgd/emgd/drm/user_config.h        |  113 +
 drivers/gpu/drm/emgd/emgd/gmm/gmm.c                | 1382 +++++++
 drivers/gpu/drm/emgd/emgd/gmm/gtt.c                |  436 +++
 drivers/gpu/drm/emgd/emgd/include/cmd.h            |   47 +
 drivers/gpu/drm/emgd/emgd/include/context.h        |  255 ++
 drivers/gpu/drm/emgd/emgd/include/debug.h          |  169 +
 drivers/gpu/drm/emgd/emgd/include/decode.h         |   76 +
 drivers/gpu/drm/emgd/emgd/include/dispatch.h       |   59 +
 drivers/gpu/drm/emgd/emgd/include/dispatch_utils.h |   78 +
 drivers/gpu/drm/emgd/emgd/include/displayid.h      |  663 ++++
 drivers/gpu/drm/emgd/emgd/include/dsp.h            |   46 +
 drivers/gpu/drm/emgd/emgd/include/edid.h           |  130 +
 drivers/gpu/drm/emgd/emgd/include/general.h        |   84 +
 drivers/gpu/drm/emgd/emgd/include/instr_common.h   |   54 +
 drivers/gpu/drm/emgd/emgd/include/intelpci.h       |   98 +
 drivers/gpu/drm/emgd/emgd/include/math_fix.h       |   59 +
 drivers/gpu/drm/emgd/emgd/include/memlist.h        |  154 +
 drivers/gpu/drm/emgd/emgd/include/memory.h         |  421 +++
 drivers/gpu/drm/emgd/emgd/include/mode.h           |  444 +++
 drivers/gpu/drm/emgd/emgd/include/mode_access.h    |   52 +
 drivers/gpu/drm/emgd/emgd/include/module_init.h    |  109 +
 drivers/gpu/drm/emgd/emgd/include/msvdx.h          |  257 ++
 drivers/gpu/drm/emgd/emgd/include/pci.h            |  257 ++
 drivers/gpu/drm/emgd/emgd/include/pd.h             |  766 ++++
 drivers/gpu/drm/emgd/emgd/include/pd_init.h        |  191 +
 drivers/gpu/drm/emgd/emgd/include/pi.h             |   86 +
 drivers/gpu/drm/emgd/emgd/include/plb/appcontext.h |   67 +
 drivers/gpu/drm/emgd/emgd/include/plb/cmd.h        |   43 +
 drivers/gpu/drm/emgd/emgd/include/plb/context.h    |  210 ++
 drivers/gpu/drm/emgd/emgd/include/plb/instr.h      |  224 ++
 drivers/gpu/drm/emgd/emgd/include/plb/mi.h         |   77 +
 drivers/gpu/drm/emgd/emgd/include/plb/regs.h       |  747 ++++
 drivers/gpu/drm/emgd/emgd/include/plb/sgx.h        |  217 ++
 drivers/gpu/drm/emgd/emgd/include/plb/state3d.h    |  398 ++
 .../gpu/drm/emgd/emgd/include/plb/state3d_plb.h    | 1299 +++++++
 drivers/gpu/drm/emgd/emgd/include/psb_regs.h       |  658 ++++
 drivers/gpu/drm/emgd/emgd/include/rb.h             |  186 +
 drivers/gpu/drm/emgd/emgd/include/reset.h          |   43 +
 drivers/gpu/drm/emgd/emgd/include/sched.h          |  197 +
 drivers/gpu/drm/emgd/emgd/include/state2d.h        |   69 +
 drivers/gpu/drm/emgd/emgd/include/tnc/appcontext.h |   40 +
 drivers/gpu/drm/emgd/emgd/include/tnc/cmd.h        |   39 +
 drivers/gpu/drm/emgd/emgd/include/tnc/context.h    |   37 +
 drivers/gpu/drm/emgd/emgd/include/tnc/igd_tnc_wa.h |  133 +
 drivers/gpu/drm/emgd/emgd/include/tnc/instr.h      |   40 +
 drivers/gpu/drm/emgd/emgd/include/tnc/mi.h         |   41 +
 drivers/gpu/drm/emgd/emgd/include/tnc/regs.h       |  889 +++++
 drivers/gpu/drm/emgd/emgd/include/tnc/sgx.h        |   36 +
 drivers/gpu/drm/emgd/emgd/include/tnc/state3d.h    |   43 +
 .../gpu/drm/emgd/emgd/include/tnc/state3d_plb.h    |   38 +
 drivers/gpu/drm/emgd/emgd/include/topaz.h          |  209 ++
 drivers/gpu/drm/emgd/emgd/include/utils.h          |  174 +
 drivers/gpu/drm/emgd/emgd/include/vga.h            |  116 +
 drivers/gpu/drm/emgd/emgd/oal/src/math_fix.c       |  138 +
 drivers/gpu/drm/emgd/emgd/oal/src/memmap.c         |   55 +
 drivers/gpu/drm/emgd/emgd/oal/src/pci.c            |  277 ++
 drivers/gpu/drm/emgd/emgd/pal/Makefile.include     |   50 +
 drivers/gpu/drm/emgd/emgd/pal/ch7036/Makefile.gnu  |   44 +
 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.c      | 2366 ++++++++++++
 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.def    |    5 +
 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.h      |   51 +
 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.c | 1061 ++++++
 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.h |   85 +
 .../drm/emgd/emgd/pal/ch7036/ch7036_def_regmap.h   |  700 ++++
 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.c   |  468 +++
 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.h   |  213 ++
 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.c  |  296 ++
 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.h  |   52 +
 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.c | 1994 ++++++++++
 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.h |  243 ++
 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_pm.c   |  492 +++
 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.c | 1548 ++++++++
 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.h |   59 +
 .../drm/emgd/emgd/pal/ch7036/ch7036_reg_table.c    |  224 ++
 .../drm/emgd/emgd/pal/ch7036/ch7036_reg_table.h    |  125 +
 .../gpu/drm/emgd/emgd/pal/ch7036/ch7036_typedef.h  |  472 +++
 drivers/gpu/drm/emgd/emgd/pal/ch7036/config_.h     |   73 +
 drivers/gpu/drm/emgd/emgd/pal/ch7036/edid7036.car  | 3362 +++++++++++++++++
 drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.c   | 1587 ++++++++
 drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.h   |  170 +
 drivers/gpu/drm/emgd/emgd/pal/lpd/lpd.c            |  114 +
 drivers/gpu/drm/emgd/emgd/pal/lpd/pd_print.h       |   65 +
 drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.c          | 1555 ++++++++
 drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.h          |  164 +
 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo.def        |   25 +
 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.c     | 1484 ++++++++
 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.h     |  141 +
 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.c     |  524 +++
 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.h     |  182 +
 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.c     |  725 ++++
 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.h     |  482 +++
 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.c     | 3898 ++++++++++++++++++++
 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.h     |   71 +
 .../state/appcontext/cmn/appcontext_dispatch.h     |   56 +
 .../emgd/state/appcontext/cmn/igd_appcontext.c     |  148 +
 .../emgd/state/appcontext/plb/appcontext_plb.c     |  207 ++
 .../gpu/drm/emgd/emgd/state/power/cmn/igd_pwr.c    |  305 ++
 .../drm/emgd/emgd/state/power/cmn/pwr_dispatch.h   |   52 +
 .../gpu/drm/emgd/emgd/state/power/plb/pwr_plb.c    |  123 +
 drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg.c      |  451 +++
 .../gpu/drm/emgd/emgd/state/reg/cmn/reg_dispatch.h |   73 +
 drivers/gpu/drm/emgd/emgd/state/reg/plb/reg_plb.c  | 1126 ++++++
 drivers/gpu/drm/emgd/emgd/state/reg/tnc/reg_tnc.c  | 1205 ++++++
 drivers/gpu/drm/emgd/emgd/utils/math_fix.c         |  138 +
 drivers/gpu/drm/emgd/emgd/utils/memmap.c           |   55 +
 drivers/gpu/drm/emgd/emgd/utils/pci.c              |  277 ++
 drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx.c      |  913 +++++
 drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_init.c | 1516 ++++++++
 drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.c  |  583 +++
 drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.h  |   78 +
 .../gpu/drm/emgd/emgd/video/overlay/cmn/igd_ovl.c  |  540 +++
 .../drm/emgd/emgd/video/overlay/cmn/micro_ovl.c    |  165 +
 .../drm/emgd/emgd/video/overlay/cmn/ovl_coeff.c    | 1127 ++++++
 .../drm/emgd/emgd/video/overlay/cmn/ovl_coeff.h    |   45 +
 .../drm/emgd/emgd/video/overlay/cmn/ovl_dispatch.h |   57 +
 .../gpu/drm/emgd/emgd/video/overlay/cmn/ovl_virt.h |  107 +
 .../emgd/emgd/video/overlay/plb/micro_ovl_plb.c    | 1725 +++++++++
 .../gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.c |  542 +++
 .../gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.h |   55 +
 .../emgd/emgd/video/overlay/plb/ovl2_regs_plb.h    |   76 +
 .../gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb.c  | 2188 +++++++++++
 .../emgd/emgd/video/overlay/plb/ovl_plb_cache.c    |  321 ++
 .../emgd/emgd/video/overlay/plb/ovl_plb_cache.h    |  161 +
 .../drm/emgd/emgd/video/overlay/plb/ovl_regs_plb.h |  185 +
 .../emgd/emgd/video/overlay/tnc/micro_ovl_tnc.c    | 1738 +++++++++
 .../emgd/emgd/video/overlay/tnc/ovl2_regs_tnc.h    |   76 +
 .../gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.c |  460 +++
 .../gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.h |   55 +
 .../drm/emgd/emgd/video/overlay/tnc/ovl_regs_tnc.h |  190 +
 .../gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc.c  | 2128 +++++++++++
 .../emgd/emgd/video/overlay/tnc/ovl_tnc_cache.c    |  246 ++
 .../emgd/emgd/video/overlay/tnc/ovl_tnc_cache.h    |  162 +
 drivers/gpu/drm/emgd/emgd/video/topaz/topaz.c      |  300 ++
 drivers/gpu/drm/emgd/emgd/video/topaz/topaz_hdr.h  |  128 +
 drivers/gpu/drm/emgd/emgd/video/topaz/topaz_init.c |  985 +++++
 drivers/gpu/drm/emgd/include/emgd_drm.h            |  916 +++++
 drivers/gpu/drm/emgd/include/emgd_shared.h         |   98 +
 drivers/gpu/drm/emgd/include/gart.h                |   38 +
 drivers/gpu/drm/emgd/include/igd.h                 | 1625 ++++++++
 drivers/gpu/drm/emgd/include/igd_2d.h              |  380 ++
 drivers/gpu/drm/emgd/include/igd_appcontext.h      |   72 +
 drivers/gpu/drm/emgd/include/igd_blend.h           |   73 +
 drivers/gpu/drm/emgd/include/igd_debug.h           |   72 +
 drivers/gpu/drm/emgd/include/igd_errno.h           |   60 +
 drivers/gpu/drm/emgd/include/igd_gart.h            |   77 +
 drivers/gpu/drm/emgd/include/igd_gmm.h             |  383 ++
 drivers/gpu/drm/emgd/include/igd_init.h            |  895 +++++
 drivers/gpu/drm/emgd/include/igd_interrupt.h       |  300 ++
 drivers/gpu/drm/emgd/include/igd_mode.h            |  935 +++++
 drivers/gpu/drm/emgd/include/igd_ovl.h             |  326 ++
 drivers/gpu/drm/emgd/include/igd_pd.h              |  544 +++
 drivers/gpu/drm/emgd/include/igd_pi.h              |  130 +
 drivers/gpu/drm/emgd/include/igd_pwr.h             |   65 +
 drivers/gpu/drm/emgd/include/igd_rb.h              |   92 +
 drivers/gpu/drm/emgd/include/igd_render.h          |  532 +++
 drivers/gpu/drm/emgd/include/igd_reset.h           |   55 +
 drivers/gpu/drm/emgd/include/igd_version.h         |   41 +
 drivers/gpu/drm/emgd/include/igd_vga.h             |   65 +
 drivers/gpu/drm/emgd/include/io.h                  |  422 +++
 drivers/gpu/drm/emgd/include/memmap.h              |  104 +
 drivers/gpu/drm/emgd/pvr/include4/dbgdrvif.h       |  263 ++
 drivers/gpu/drm/emgd/pvr/include4/img_defs.h       |  104 +
 drivers/gpu/drm/emgd/pvr/include4/img_types.h      |  124 +
 drivers/gpu/drm/emgd/pvr/include4/ioctldef.h       |   94 +
 drivers/gpu/drm/emgd/pvr/include4/pdumpdefs.h      |   95 +
 drivers/gpu/drm/emgd/pvr/include4/pvr_debug.h      |  123 +
 drivers/gpu/drm/emgd/pvr/include4/pvrmodule.h      |   27 +
 drivers/gpu/drm/emgd/pvr/include4/pvrversion.h     |   34 +
 drivers/gpu/drm/emgd/pvr/include4/regpaths.h       |   39 +
 drivers/gpu/drm/emgd/pvr/include4/services.h       |  866 +++++
 drivers/gpu/drm/emgd/pvr/include4/servicesext.h    |  647 ++++
 drivers/gpu/drm/emgd/pvr/include4/sgx_options.h    |  220 ++
 drivers/gpu/drm/emgd/pvr/include4/sgxapi_km.h      |  323 ++
 drivers/gpu/drm/emgd/pvr/include4/sgxscript.h      |   77 +
 .../services4/3rdparty/emgd_bufferclass/emgd_bc.c  |  384 ++
 .../services4/3rdparty/emgd_bufferclass/emgd_bc.h  |  173 +
 .../3rdparty/emgd_bufferclass/emgd_bc_linux.c      | 1000 +++++
 .../services4/3rdparty/emgd_displayclass/emgd_dc.c | 2814 ++++++++++++++
 .../services4/3rdparty/emgd_displayclass/emgd_dc.h |  342 ++
 .../3rdparty/emgd_displayclass/emgd_dc_linux.c     |  153 +
 .../services4/include/env/linux/pvr_drm_shared.h   |   59 +
 .../drm/emgd/pvr/services4/include/kernelbuffer.h  |   57 +
 .../drm/emgd/pvr/services4/include/kerneldisplay.h |  152 +
 .../drm/emgd/pvr/services4/include/pvr_bridge.h    | 1380 +++++++
 .../drm/emgd/pvr/services4/include/pvr_bridge_km.h |  292 ++
 .../gpu/drm/emgd/pvr/services4/include/pvrmmap.h   |   32 +
 .../drm/emgd/pvr/services4/include/pvrsrv_errors.h |  189 +
 .../drm/emgd/pvr/services4/include/servicesint.h   |  272 ++
 .../drm/emgd/pvr/services4/include/sgx_bridge.h    |  473 +++
 .../drm/emgd/pvr/services4/include/sgx_mkif_km.h   |  339 ++
 .../gpu/drm/emgd/pvr/services4/include/sgxinfo.h   |  288 ++
 .../services4/srvkm/bridged/bridged_pvr_bridge.c   | 3447 +++++++++++++++++
 .../services4/srvkm/bridged/bridged_pvr_bridge.h   |  227 ++
 .../pvr/services4/srvkm/bridged/bridged_support.c  |   81 +
 .../pvr/services4/srvkm/bridged/bridged_support.h  |   39 +
 .../srvkm/bridged/sgx/bridged_sgx_bridge.c         | 2510 +++++++++++++
 .../srvkm/bridged/sgx/bridged_sgx_bridge.h         |   38 +
 .../pvr/services4/srvkm/common/buffer_manager.c    | 2069 +++++++++++
 .../emgd/pvr/services4/srvkm/common/deviceclass.c  | 2060 +++++++++++
 .../emgd/pvr/services4/srvkm/common/devicemem.c    | 1546 ++++++++
 .../drm/emgd/pvr/services4/srvkm/common/handle.c   | 1545 ++++++++
 .../gpu/drm/emgd/pvr/services4/srvkm/common/hash.c |  459 +++
 .../drm/emgd/pvr/services4/srvkm/common/lists.c    |   95 +
 .../gpu/drm/emgd/pvr/services4/srvkm/common/mem.c  |  147 +
 .../emgd/pvr/services4/srvkm/common/mem_debug.c    |  246 ++
 .../drm/emgd/pvr/services4/srvkm/common/metrics.c  |  156 +
 .../emgd/pvr/services4/srvkm/common/pdump_common.c | 1723 +++++++++
 .../drm/emgd/pvr/services4/srvkm/common/perproc.c  |  279 ++
 .../drm/emgd/pvr/services4/srvkm/common/power.c    |  743 ++++
 .../drm/emgd/pvr/services4/srvkm/common/pvrsrv.c   | 1194 ++++++
 .../drm/emgd/pvr/services4/srvkm/common/queue.c    | 1161 ++++++
 .../gpu/drm/emgd/pvr/services4/srvkm/common/ra.c   | 1867 ++++++++++
 .../drm/emgd/pvr/services4/srvkm/common/resman.c   |  704 ++++
 .../drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.c | 2772 ++++++++++++++
 .../drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.h |  135 +
 .../drm/emgd/pvr/services4/srvkm/devices/sgx/pb.c  |  454 +++
 .../services4/srvkm/devices/sgx/sgx_bridge_km.h    |  143 +
 .../pvr/services4/srvkm/devices/sgx/sgxconfig.h    |  161 +
 .../pvr/services4/srvkm/devices/sgx/sgxinfokm.h    |  348 ++
 .../emgd/pvr/services4/srvkm/devices/sgx/sgxinit.c | 2267 ++++++++++++
 .../emgd/pvr/services4/srvkm/devices/sgx/sgxkick.c |  740 ++++
 .../pvr/services4/srvkm/devices/sgx/sgxpower.c     |  465 +++
 .../pvr/services4/srvkm/devices/sgx/sgxreset.c     |  485 +++
 .../pvr/services4/srvkm/devices/sgx/sgxtransfer.c  |  549 +++
 .../pvr/services4/srvkm/devices/sgx/sgxutils.c     | 1054 ++++++
 .../pvr/services4/srvkm/devices/sgx/sgxutils.h     |   95 +
 .../emgd/pvr/services4/srvkm/env/linux/env_data.h  |   62 +
 .../pvr/services4/srvkm/env/linux/env_perproc.h    |   52 +
 .../drm/emgd/pvr/services4/srvkm/env/linux/event.c |  267 ++
 .../drm/emgd/pvr/services4/srvkm/env/linux/event.h |   28 +
 .../pvr/services4/srvkm/env/linux/kbuild/Makefile  |  151 +
 .../emgd/pvr/services4/srvkm/env/linux/linkage.h   |   57 +
 .../drm/emgd/pvr/services4/srvkm/env/linux/lock.h  |   28 +
 .../drm/emgd/pvr/services4/srvkm/env/linux/mm.c    | 2377 ++++++++++++
 .../drm/emgd/pvr/services4/srvkm/env/linux/mm.h    |  323 ++
 .../drm/emgd/pvr/services4/srvkm/env/linux/mmap.c  | 1149 ++++++
 .../drm/emgd/pvr/services4/srvkm/env/linux/mmap.h  |  103 +
 .../emgd/pvr/services4/srvkm/env/linux/module.c    |  756 ++++
 .../drm/emgd/pvr/services4/srvkm/env/linux/mutex.c |   28 +
 .../drm/emgd/pvr/services4/srvkm/env/linux/mutex.h |   37 +
 .../emgd/pvr/services4/srvkm/env/linux/mutils.c    |  126 +
 .../emgd/pvr/services4/srvkm/env/linux/mutils.h    |   93 +
 .../emgd/pvr/services4/srvkm/env/linux/osfunc.c    | 2529 +++++++++++++
 .../emgd/pvr/services4/srvkm/env/linux/osperproc.c |  109 +
 .../drm/emgd/pvr/services4/srvkm/env/linux/pdump.c |  658 ++++
 .../pvr/services4/srvkm/env/linux/private_data.h   |   63 +
 .../drm/emgd/pvr/services4/srvkm/env/linux/proc.c  |  962 +++++
 .../drm/emgd/pvr/services4/srvkm/env/linux/proc.h  |  111 +
 .../pvr/services4/srvkm/env/linux/pvr_bridge_k.c   |  647 ++++
 .../emgd/pvr/services4/srvkm/env/linux/pvr_debug.c |  418 +++
 .../emgd/pvr/services4/srvkm/env/linux/pvr_drm.c   |  301 ++
 .../emgd/pvr/services4/srvkm/env/linux/pvr_drm.h   |   65 +
 .../emgd/pvr/services4/srvkm/hwdefs/sgx535defs.h   |  633 ++++
 .../emgd/pvr/services4/srvkm/hwdefs/sgx540defs.h   |  586 +++
 .../emgd/pvr/services4/srvkm/hwdefs/sgx545defs.h   |  828 +++++
 .../drm/emgd/pvr/services4/srvkm/hwdefs/sgxdefs.h  |   78 +
 .../emgd/pvr/services4/srvkm/hwdefs/sgxerrata.h    |  310 ++
 .../pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h    |  159 +
 .../drm/emgd/pvr/services4/srvkm/hwdefs/sgxmmu.h   |   75 +
 .../pvr/services4/srvkm/include/buffer_manager.h   |  214 ++
 .../drm/emgd/pvr/services4/srvkm/include/device.h  |  274 ++
 .../drm/emgd/pvr/services4/srvkm/include/handle.h  |  378 ++
 .../drm/emgd/pvr/services4/srvkm/include/hash.h    |   69 +
 .../drm/emgd/pvr/services4/srvkm/include/lists.h   |  172 +
 .../drm/emgd/pvr/services4/srvkm/include/metrics.h |  126 +
 .../drm/emgd/pvr/services4/srvkm/include/osfunc.h  |  483 +++
 .../emgd/pvr/services4/srvkm/include/osperproc.h   |   72 +
 .../emgd/pvr/services4/srvkm/include/pdump_km.h    |  448 +++
 .../pvr/services4/srvkm/include/pdump_osfunc.h     |  133 +
 .../drm/emgd/pvr/services4/srvkm/include/perproc.h |  106 +
 .../drm/emgd/pvr/services4/srvkm/include/power.h   |  116 +
 .../drm/emgd/pvr/services4/srvkm/include/queue.h   |  115 +
 .../gpu/drm/emgd/pvr/services4/srvkm/include/ra.h  |  151 +
 .../drm/emgd/pvr/services4/srvkm/include/resman.h  |  109 +
 .../pvr/services4/srvkm/include/services_headers.h |   45 +
 .../drm/emgd/pvr/services4/srvkm/include/srvkm.h   |   65 +
 .../emgd/pvr/services4/system/common/sysconfig.c   | 1367 +++++++
 .../emgd/pvr/services4/system/common/sysutils.c    |   26 +
 .../emgd/pvr/services4/system/include/oemfuncs.h   |   68 +
 .../services4/system/include/sys_pvr_drm_shared.h  |   34 +
 .../emgd/pvr/services4/system/include/syscommon.h  |   27 +
 .../emgd/pvr/services4/system/include/sysconfig.h  |  326 ++
 .../emgd/pvr/services4/system/include/sysinfo.h    |   42 +
 .../emgd/pvr/services4/system/include/syslocal.h   |   80 +
 .../drm/emgd/pvr/services4/system/plb/sysconfig.c  |   48 +
 .../gpu/drm/emgd/pvr/services4/system/plb/sysplb.h |   33 +
 .../drm/emgd/pvr/services4/system/tnc/sysconfig.c  |   48 +
 .../gpu/drm/emgd/pvr/services4/system/tnc/systnc.h |   33 +
 .../emgd/pvr/tools/intern/debug/client/linuxsrv.h  |   44 +
 .../tools/intern/debug/dbgdriv/common/dbgdriv.c    | 2072 +++++++++++
 .../tools/intern/debug/dbgdriv/common/dbgdriv.h    |  112 +
 .../tools/intern/debug/dbgdriv/common/hostfunc.h   |   54 +
 .../pvr/tools/intern/debug/dbgdriv/common/hotkey.c |  131 +
 .../pvr/tools/intern/debug/dbgdriv/common/hotkey.h |   56 +
 .../pvr/tools/intern/debug/dbgdriv/common/ioctl.c  |  367 ++
 .../pvr/tools/intern/debug/dbgdriv/common/ioctl.h  |   83 +
 .../tools/intern/debug/dbgdriv/linux/hostfunc.c    |  300 ++
 .../intern/debug/dbgdriv/linux/kbuild/Makefile     |   33 +
 .../pvr/tools/intern/debug/dbgdriv/linux/main.c    |  294 ++
 .../debug/dbgdriv/linux/makefile.linux.common      |   38 +
 357 files changed, 187142 insertions(+), 0 deletions(-)
 create mode 100755 drivers/gpu/drm/emgd/Makefile
 create mode 100644 drivers/gpu/drm/emgd/emgd/cfg/config.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/cfg/config_default.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/cfg/config_helper.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_global.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_init.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/core/init/cmn/init_dispatch.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/core/init/plb/init_plb.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/core/init/plb/micro_init_plb.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/core/init/tnc/init_tnc.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/core/init/tnc/micro_init_tnc.c
 create mode 100755 drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp_dispatch.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/dsp/plb/dsp_plb.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/dsp/tnc/dsp_tnc.c
 create mode 100755 drivers/gpu/drm/emgd/emgd/display/mode/cmn/igd_mode.c
 create mode 100755 drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.c
 create mode 100755 drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/cmn/micro_mode.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/cmn/mode_dispatch.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/cmn/vga_mode.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/plb/clocks_plb.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/plb/kms_mode_plb.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/plb/micro_mode_plb.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/plb/mode_plb.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/plb/mode_plb.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/tnc/clocks_tnc.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/tnc/kms_mode_tnc.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/tnc/micro_mode_tnc.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.h
 create mode 100755 drivers/gpu/drm/emgd/emgd/display/pd/cmn/pd.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/pi/cmn/displayid.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/pi/cmn/edid.c
 create mode 100755 drivers/gpu/drm/emgd/emgd/display/pi/cmn/i2c_dispatch.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/pi/cmn/igd_pi.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/pi/cmn/mode_table.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/pi/cmn/pd_init_all.c
 create mode 100755 drivers/gpu/drm/emgd/emgd/display/pi/cmn/pi.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/pi/plb/i2c_plb.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/pi/tnc/i2c_bitbash_tnc.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/display/pi/tnc/i2c_gmbus_tnc.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/drm/drm_emgd_private.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_connector.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_crtc.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_drv.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_drv.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_encoder.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_fb.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_fbcon.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_interface.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_mmap.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/drm/emgd_test_pvrsrv.c
 create mode 100755 drivers/gpu/drm/emgd/emgd/drm/image_data.h
 create mode 100755 drivers/gpu/drm/emgd/emgd/drm/splash_screen.c
 create mode 100755 drivers/gpu/drm/emgd/emgd/drm/splash_screen.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/drm/user_config.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/drm/user_config.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/gmm/gmm.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/gmm/gtt.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/cmd.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/context.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/debug.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/decode.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/dispatch.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/dispatch_utils.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/displayid.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/dsp.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/edid.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/general.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/instr_common.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/intelpci.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/math_fix.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/memlist.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/memory.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/mode.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/mode_access.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/module_init.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/msvdx.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/pci.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/pd.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/pd_init.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/pi.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/appcontext.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/cmd.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/context.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/instr.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/mi.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/regs.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/sgx.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/state3d.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/plb/state3d_plb.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/psb_regs.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/rb.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/reset.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/sched.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/state2d.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/appcontext.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/cmd.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/context.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/igd_tnc_wa.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/instr.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/mi.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/regs.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/sgx.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/state3d.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/tnc/state3d_plb.h
 create mode 100755 drivers/gpu/drm/emgd/emgd/include/topaz.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/utils.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/include/vga.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/oal/src/math_fix.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/oal/src/memmap.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/oal/src/pci.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/Makefile.include
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/Makefile.gnu
 create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.def
 create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.h
 create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_def_regmap.h
 create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.c
 create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.h
 create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.c
 create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.h
 create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_pm.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.h
 create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_reg_table.c
 create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_reg_table.h
 create mode 100755 drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_typedef.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/config_.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/edid7036.car
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/lpd/lpd.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/lpd/pd_print.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo.def
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/state/appcontext/cmn/appcontext_dispatch.h
 create mode 100755 drivers/gpu/drm/emgd/emgd/state/appcontext/cmn/igd_appcontext.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/state/appcontext/plb/appcontext_plb.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/state/power/cmn/igd_pwr.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/state/power/cmn/pwr_dispatch.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/state/power/plb/pwr_plb.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg_dispatch.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/state/reg/plb/reg_plb.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/state/reg/tnc/reg_tnc.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/utils/math_fix.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/utils/memmap.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/utils/pci.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_init.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/cmn/igd_ovl.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/cmn/micro_ovl.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_coeff.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_coeff.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_dispatch.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_virt.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/plb/micro_ovl_plb.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_regs_plb.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb_cache.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb_cache.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_regs_plb.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/tnc/micro_ovl_tnc.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_regs_tnc.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_regs_tnc.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc_cache.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc_cache.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/topaz/topaz.c
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/topaz/topaz_hdr.h
 create mode 100644 drivers/gpu/drm/emgd/emgd/video/topaz/topaz_init.c
 create mode 100644 drivers/gpu/drm/emgd/include/emgd_drm.h
 create mode 100644 drivers/gpu/drm/emgd/include/emgd_shared.h
 create mode 100644 drivers/gpu/drm/emgd/include/gart.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_2d.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_appcontext.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_blend.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_debug.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_errno.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_gart.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_gmm.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_init.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_interrupt.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_mode.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_ovl.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_pd.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_pi.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_pwr.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_rb.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_render.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_reset.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_version.h
 create mode 100644 drivers/gpu/drm/emgd/include/igd_vga.h
 create mode 100644 drivers/gpu/drm/emgd/include/io.h
 create mode 100644 drivers/gpu/drm/emgd/include/memmap.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/include4/dbgdrvif.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/include4/img_defs.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/include4/img_types.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/include4/ioctldef.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/include4/pdumpdefs.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/include4/pvr_debug.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/include4/pvrmodule.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/include4/pvrversion.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/include4/regpaths.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/include4/services.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/include4/servicesext.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/include4/sgx_options.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/include4/sgxapi_km.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/include4/sgxscript.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc_linux.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc_linux.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/env/linux/pvr_drm_shared.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/kernelbuffer.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/kerneldisplay.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/pvr_bridge.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/pvr_bridge_km.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/pvrmmap.h
 create mode 100755 drivers/gpu/drm/emgd/pvr/services4/include/pvrsrv_errors.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/servicesint.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/sgx_bridge.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/sgx_mkif_km.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/include/sgxinfo.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_pvr_bridge.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_pvr_bridge.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_support.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_support.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/buffer_manager.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/deviceclass.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/devicemem.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/handle.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/hash.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/lists.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/mem.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/mem_debug.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/metrics.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/pdump_common.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/perproc.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/power.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/pvrsrv.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/queue.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/ra.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/common/resman.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/pb.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxconfig.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxinfokm.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxinit.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxkick.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxpower.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxreset.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxtransfer.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxutils.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxutils.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/env_data.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/env_perproc.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/event.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/event.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/kbuild/Makefile
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/linkage.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/lock.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mm.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mm.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/module.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutex.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutex.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutils.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutils.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/osfunc.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/osperproc.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pdump.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/private_data.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/proc.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/proc.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_bridge_k.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_debug.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_drm.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_drm.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx535defs.h
 create mode 100755 drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx540defs.h
 create mode 100755 drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx545defs.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxdefs.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxerrata.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxmmu.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/buffer_manager.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/device.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/handle.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/hash.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/lists.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/metrics.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/osfunc.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/osperproc.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/pdump_km.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/pdump_osfunc.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/perproc.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/power.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/queue.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/ra.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/resman.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/services_headers.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/srvkm/include/srvkm.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/common/sysconfig.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/common/sysutils.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/include/oemfuncs.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/include/sys_pvr_drm_shared.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/include/syscommon.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/include/sysconfig.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/include/sysinfo.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/include/syslocal.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/plb/sysconfig.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/plb/sysplb.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/tnc/sysconfig.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/services4/system/tnc/systnc.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/client/linuxsrv.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hostfunc.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hotkey.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hotkey.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/ioctl.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/ioctl.h
 create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/hostfunc.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/kbuild/Makefile
 create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/main.c
 create mode 100644 drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/makefile.linux.common

diff --git a/drivers/gpu/drm/emgd/Makefile b/drivers/gpu/drm/emgd/Makefile
new file mode 100755
index 0000000..c4bd102
--- /dev/null
+++ b/drivers/gpu/drm/emgd/Makefile
@@ -0,0 +1,332 @@
+#----------------------------------------------------------------------------
+# Filename: Makefile.gnu
+# $Revision: 1.58 $
+#----------------------------------------------------------------------------
+# Copyright (c) 2002-2010, Intel Corporation.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#----------------------------------------------------------------------------
+export EGD_TOPLEVEL = DRM Driver
+
+KERNELVER ?= $(shell uname -r)
+KERNELDIR ?= /lib/modules/$(KERNELVER)/build
+INSTALLDIR ?= /lib/modules/$(KERNELVER)/kernel/drivers/gpu/drm/emgd
+
+BLUE = \033[34m
+OFF = \033[0m
+BUILD ?= release
+CONFIG_PVR_RELEASE ?= $(BUILD)
+CONFIG_DRM_EGD ?= m
+
+# Get the include paths pointed to the right place. 
+export  EMGD_MOD_DIR ?= $(CURDIR)
+
+BUILDDATE ?= $(shell date +%Y%m%d)
+
+PROJECT_INCLUDES = \
+	   -I$(EMGD_MOD_DIR)/include \
+	   -I$(EMGD_MOD_DIR)/emgd/display/mode/cmn \
+	   -I$(EMGD_MOD_DIR)/emgd/video/overlay/cmn \
+	   -I$(EMGD_MOD_DIR)/emgd/video/msvdx \
+	   -I$(EMGD_MOD_DIR)/emgd/include \
+	   -I$(EMGD_MOD_DIR)/emgd/cfg \
+	   -I$(EMGD_MOD_DIR)/emgd/pal/lpd \
+	   -I$(EMGD_MOD_DIR)/emgd/pal/lvds \
+	   -I$(EMGD_MOD_DIR)/emgd/pal/ch7036 \
+	   -I$(EMGD_MOD_DIR)/emgd/drm \
+	   -I$(KERNELDIR)/include/drm \
+	   -I/usr/src/linux-headers-2.6.32-5-common/include/drm \
+	   -I$(EMGD_MOD_DIR)/pvr/include4 \
+	   -I$(EMGD_MOD_DIR)/pvr/services4/include \
+	   -I$(EMGD_MOD_DIR)/pvr/services4/include/env/linux \
+	   -I$(EMGD_MOD_DIR)/pvr/services4/srvkm/env/linux \
+	   -I$(EMGD_MOD_DIR)/pvr/services4/srvkm/include \
+	   -I$(EMGD_MOD_DIR)/pvr/services4/srvkm/bridged \
+	   -I$(EMGD_MOD_DIR)/pvr/services4/system/plb \
+	   -I$(EMGD_MOD_DIR)/pvr/services4/system/tnc \
+	   -I$(EMGD_MOD_DIR)/pvr/services4/system/include \
+	   -I$(EMGD_MOD_DIR)/pvr/services4/srvkm/hwdefs \
+	   -I$(EMGD_MOD_DIR)/pvr/services4/srvkm/bridged/sgx \
+	   -I$(EMGD_MOD_DIR)/pvr/services4/srvkm/devices/sgx \
+	   -I$(EMGD_MOD_DIR)/pvr/services4/3rdparty/emgd_bufferclass \
+	   -I$(EMGD_MOD_DIR)/pvr/tools/intern/debug \
+	   -DSUPPORT_DRI_DRM_EXT \
+	   -DLINUX \
+	   -DPVR_BUILD_DIR="\"emgd\"" \
+	   -DPVR_BUILD_DATE="\"$(BUILDDATE)\"" \
+	   -DPVR_BUILD_TYPE="\"$(CONFIG_PVR_RELEASE)\"" \
+	   -DBUILD=$(CONFIG_PVR_RELEASE) \
+	   -DPVR_SECURE_HANDLES \
+	   -DPVR_PROC_USE_SEQ_FILE \
+	   -DLDM_PCI \
+	   -DSUPPORT_CACHEFLUSH_ON_ALLOC \
+	   -DSUPPORT_DRI_DRM \
+	   -DSGX535 \
+	   -DSGX_CORE_REV=121 \
+	   -UDEBUG_LOG_PATH_TRUNCATE \
+	   -DDISPLAY_CONTROLLER=emgd_dc \
+	   -D_XOPEN_SOURCE=600 \
+	   -DSERVICES4 \
+	   -DPVR2D_VALIDATE_INPUT_PARAMS \
+	   -DSUPPORT_SRVINIT \
+	   -DSUPPORT_SGX \
+	   -DSUPPORT_PERCONTEXT_PB \
+	   -DSUPPORT_LINUX_X86_WRITECOMBINE \
+	   -DSUPPORT_SECURE_DRM_AUTH_EXPORT \
+	   -DSUPPORT_PDUMP_DELAYED_INITPHASE_TERMINATION \
+	   -DTRANSFER_QUEUE \
+	   -DSYS_USING_INTERRUPTS \
+	   -DSUPPORT_HW_RECOVERY \
+	   -DSUPPORT_ACTIVE_POWER_MANAGEMENT \
+	   -DPVR_SECURE_HANDLES \
+	   -DUSE_PTHREADS \
+	   -DSUPPORT_SGX_EVENT_OBJECT \
+	   -DSUPPORT_SGX_HWPERF \
+	   -DSUPPORT_SGX_LOW_LATENCY_SCHEDULING \
+	   -DSUPPORT_LINUX_X86_PAT \
+	   -DSUPPORT_SGX535 \
+	   -DSUPPORT_CACHE_LINE_FLUSH \
+	   -DSUPPORT_CPU_CACHED_BUFFERS \
+	   -DDEBUG_MESA_OGL_TRACE \
+	   -DSUPPORT_EGL_IMAGE_SYNC_DEPENDENCY \
+
+
+ifeq "$(strip $(CONFIG_PVR_RELEASE))" "release"
+	ccflags-y += -DRELEASE
+else
+	# FIXME: Looks like this causes conflicts in the emgd code.
+	ccflags-y += -DDEBUG
+	ccflags-y += -DDEBUG_BUILD_TYPE 
+endif
+
+EXTRA_CFLAGS += $(PROJECT_INCLUDES)
+
+ifeq ($(PDUMP),1)
+	EXTRA_CFLAGS += -DPDUMP=1
+endif
+
+EMGD_OBJS := \
+	emgd/drm/emgd_fb.o \
+	emgd/drm/emgd_fbcon.o \
+	emgd/drm/emgd_crtc.o \
+	emgd/drm/emgd_encoder.o \
+	emgd/drm/emgd_connector.o \
+	emgd/drm/emgd_mmap.o \
+	emgd/drm/emgd_drv.o \
+	emgd/drm/emgd_interface.o \
+	emgd/drm/emgd_test_pvrsrv.o \
+	emgd/drm/user_config.o \
+	emgd/drm/splash_screen.o \
+	emgd/display/pd/cmn/pd.o \
+	emgd/display/pi/cmn/igd_pi.o \
+	emgd/display/pi/cmn/displayid.o \
+	emgd/display/pi/cmn/pd_init_all.o \
+	emgd/display/pi/cmn/edid.o \
+	emgd/display/pi/cmn/pi.o \
+	emgd/display/pi/cmn/mode_table.o \
+	emgd/display/pi/tnc/i2c_gmbus_tnc.o \
+	emgd/display/pi/tnc/i2c_bitbash_tnc.o \
+	emgd/display/pi/plb/i2c_plb.o \
+	emgd/display/mode/cmn/match.o \
+	emgd/display/mode/cmn/micro_mode.o \
+	emgd/display/mode/cmn/vga_mode.o \
+	emgd/display/mode/cmn/igd_mode.o \
+	emgd/display/mode/tnc/micro_mode_tnc.o \
+	emgd/display/mode/tnc/mode_tnc.o \
+	emgd/display/mode/tnc/kms_mode_tnc.o \
+	emgd/display/mode/tnc/clocks_tnc.o \
+	emgd/display/mode/plb/micro_mode_plb.o \
+	emgd/display/mode/plb/clocks_plb.o \
+	emgd/display/mode/plb/mode_plb.o \
+	emgd/display/mode/plb/kms_mode_plb.o \
+	emgd/display/dsp/cmn/dsp.o \
+	emgd/display/dsp/tnc/dsp_tnc.o \
+	emgd/display/dsp/plb/dsp_plb.o \
+	emgd/core/init/cmn/igd_global.o \
+	emgd/core/init/cmn/igd_init.o \
+	emgd/core/init/tnc/micro_init_tnc.o \
+	emgd/core/init/tnc/init_tnc.o \
+	emgd/core/init/plb/init_plb.o \
+	emgd/core/init/plb/micro_init_plb.o \
+	emgd/state/power/cmn/igd_pwr.o \
+	emgd/state/power/plb/pwr_plb.o \
+	emgd/state/appcontext/cmn/igd_appcontext.o \
+	emgd/state/appcontext/plb/appcontext_plb.o \
+	emgd/state/reg/cmn/reg.o \
+	emgd/state/reg/tnc/reg_tnc.o \
+	emgd/state/reg/plb/reg_plb.o \
+	emgd/video/overlay/cmn/ovl_coeff.o \
+	emgd/video/overlay/cmn/igd_ovl.o \
+	emgd/video/overlay/cmn/micro_ovl.o \
+	emgd/video/overlay/tnc/ovl_tnc_cache.o \
+	emgd/video/overlay/tnc/ovl_tnc.o \
+	emgd/video/overlay/tnc/ovl2_tnc.o \
+	emgd/video/overlay/tnc/micro_ovl_tnc.o \
+	emgd/video/overlay/plb/ovl_plb_cache.o \
+	emgd/video/overlay/plb/ovl2_plb.o \
+	emgd/video/overlay/plb/ovl_plb.o \
+	emgd/video/overlay/plb/micro_ovl_plb.o \
+	emgd/video/msvdx/msvdx_init.o \
+	emgd/video/msvdx/msvdx.o \
+	emgd/video/msvdx/msvdx_pvr.o \
+	emgd/video/topaz/topaz_init.o \
+	emgd/video/topaz/topaz.o \
+	emgd/pal/sdvo/sdvo_attr.o \
+	emgd/pal/sdvo/sdvo_hdmi.o \
+	emgd/pal/sdvo/sdvo_port.o \
+	emgd/pal/sdvo/sdvo_intf.o \
+	emgd/pal/ch7036/ch7036_attr.o \
+	emgd/pal/ch7036/ch7036_fw.o \
+	emgd/pal/ch7036/ch7036_intf.o \
+	emgd/pal/ch7036/ch7036_port.o \
+	emgd/pal/ch7036/ch7036.o \
+	emgd/pal/ch7036/ch7036_iic.o \
+	emgd/pal/ch7036/ch7036_pm.o \
+	emgd/pal/ch7036/ch7036_reg_table.o \
+	emgd/pal/ch7036/lvds/lvds.o \
+	emgd/pal/lvds/lvds.o \
+	emgd/pal/lpd/lpd.o \
+	emgd/gmm/gmm.o \
+	emgd/gmm/gtt.o \
+	emgd/utils/pci.o \
+	emgd/utils/memmap.o \
+	emgd/utils/math_fix.o \
+
+ENVDIR = pvr/services4/srvkm/env/linux
+COMMONDIR = pvr/services4/srvkm/common
+BRIDGEDDIR = pvr/services4/srvkm/bridged
+SYSCONFIGDIR = pvr/services4/system/common
+SGXDIR = pvr/services4/srvkm/devices/sgx
+DISPCLASSDIR = pvr/services4/3rdparty/emgd_displayclass
+BUFFERCLASSDIR = pvr/services4/3rdparty/emgd_bufferclass
+
+ifeq ($(PDUMP),1)
+DBGDRVDIR = pvr/tools/intern/debug/dbgdriv
+
+DBGDRV_OBJS = $(DBGDRVDIR)/linux/main.o \
+              $(DBGDRVDIR)/common/dbgdriv.o \
+              $(DBGDRVDIR)/common/ioctl.o \
+              $(DBGDRVDIR)/linux/hostfunc.o \
+              $(DBGDRVDIR)/common/hotkey.o
+endif
+
+ENV_OBJS = $(ENVDIR)/osfunc.o \
+	   $(ENVDIR)/mutils.o \
+	   $(ENVDIR)/mmap.o \
+	   $(ENVDIR)/module.o \
+	   $(ENVDIR)/pdump.o \
+	   $(ENVDIR)/proc.o \
+	   $(ENVDIR)/pvr_bridge_k.o \
+	   $(ENVDIR)/pvr_debug.o \
+	   $(ENVDIR)/mm.o \
+	   $(ENVDIR)/mutex.o \
+	   $(ENVDIR)/event.o \
+	   $(ENVDIR)/osperproc.o \
+	   $(ENVDIR)/pvr_drm.o
+
+COMMON_OBJS = $(COMMONDIR)/buffer_manager.o \
+	    $(COMMONDIR)/devicemem.o \
+	    $(COMMONDIR)/deviceclass.o \
+	    $(COMMONDIR)/handle.o \
+	    $(COMMONDIR)/hash.o \
+	    $(COMMONDIR)/metrics.o \
+	    $(COMMONDIR)/pvrsrv.o \
+	    $(COMMONDIR)/queue.o \
+	    $(COMMONDIR)/ra.o \
+	    $(COMMONDIR)/resman.o \
+	    $(COMMONDIR)/power.o \
+	    $(COMMONDIR)/mem.o \
+	    $(COMMONDIR)/pdump_common.o \
+	    $(COMMONDIR)/perproc.o \
+	    $(COMMONDIR)/lists.o \
+	    $(COMMONDIR)/mem_debug.o
+
+BRIDGED_OBJS = $(BRIDGEDDIR)/bridged_support.o \
+	     $(BRIDGEDDIR)/bridged_pvr_bridge.o \
+	     $(BRIDGEDDIR)/sgx/bridged_sgx_bridge.o
+
+SYSCONFIG_OBJS = $(SYSCONFIGDIR)/sysconfig.o \
+	        pvr/services4/system/tnc/sysconfig.o \
+	        pvr/services4/system/plb/sysconfig.o \
+		$(SYSCONFIGDIR)/sysutils.o
+#		 $(SYSCONFIGDIR)/sysirq.o
+#	 	 $(SYSCONFIGDIR)/ospm_power.o \
+
+SGX_OBJS = $(SGXDIR)/sgxinit.o \
+	 $(SGXDIR)/sgxpower.o \
+	 $(SGXDIR)/sgxreset.o \
+	 $(SGXDIR)/sgxutils.o \
+	 $(SGXDIR)/sgxkick.o \
+	 $(SGXDIR)/sgxtransfer.o \
+	 $(SGXDIR)/mmu.o \
+	 $(SGXDIR)/pb.o
+
+DC_OBJS = $(DISPCLASSDIR)/emgd_dc.o \
+	  $(DISPCLASSDIR)/emgd_dc_linux.o
+
+BC_OBJS = $(BUFFERCLASSDIR)/emgd_bc.o \
+	  $(BUFFERCLASSDIR)/emgd_bc_linux.o
+
+
+emgd-y := \
+	$(DC_OBJS) \
+	$(EMGD_OBJS) \
+	$(ENV_OBJS) \
+	$(COMMON_OBJS) \
+	$(BRIDGED_OBJS) \
+	$(SYSCONFIG_OBJS) \
+	$(SGX_OBJS) \
+	$(BC_OBJS) \
+
+ifeq ($(PDUMP),1)
+	emgd-y += $(DBGDRV_OBJS)
+endif
+
+obj-$(CONFIG_DRM_EGD) += emgd.o
+
+all:: clean modules
+
+modules::
+	@echo $(CURDIR) -- $(CONFIG_PVR_RELEASE)
+	@echo "$(MAKE) -C $(KERNELDIR) M=$(CURDIR) modules"
+	@$(MAKE) -C $(KERNELDIR) M=$(CURDIR) modules
+
+clean::
+	@rm -f $(emgd-y)
+	@rm -f emgd.o emgd.mod.* emgd.ko Module.* modules.order
+	@find . -name "*.cmd" -exec rm '{}' \;
+
+install::
+	install -o root -g root -m 755 -d $(INSTALLDIR)
+	install -o root -g root -m 744 emgd.ko $(INSTALLDIR)
+	/sbin/depmod -a
+
+uninstall::
+	rmmod $(INSTALLDIR)/emgd.ko
+	rm -rf $(INSTALLDIR)/emgd.ko
+	/sbin/depmod -a
+
+debug::
+	export CONFIG_PVR_RELEASE=debug; $(MAKE) modules
+
+package:: clean
+	@echo -e "$(BLUE)Packaging $(EGD_TOPLEVEL)$(OFF)";
+	mkdir -p $(EGD_PKG)
+	tar -C $(EMGD_MOD_DIR) --exclude "CVS" -czf $(EGD_PKG)/emgd_drm.tgz *
+
diff --git a/drivers/gpu/drm/emgd/emgd/cfg/config.h b/drivers/gpu/drm/emgd/emgd/cfg/config.h
new file mode 100644
index 0000000..14e7ca8
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/cfg/config.h
@@ -0,0 +1,113 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: config.h
+ * $Revision: 1.14 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains the compile options for the IGD compile. It is included
+ *  by all IGD OAL and RAL modules. Do not remove valid options from this
+ *  file, simply comment them out.
+ *  Eventually a config tool will auto generate this file based on selected
+ *  options.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _HAL_CONFIG_H
+#define _HAL_CONFIG_H
+
+/*
+ * Which Cores are supported
+ *
+ * Use Defaults
+ */
+
+/*
+ * This macro configures the DRM/kernel's EMGD_DEBUG() and EMGD_DEBUG_S() macros to
+ * use the KERN_INFO message priority, instead of the normal KERN_DEBUG message
+ * priority.  This is useful for bugs (e.g. crashes) where dmesg can't be used
+ * to obtain debug messages.
+ */
+/* #define CONFIG_USE_INFO_PRIORITY */
+
+
+/*
+ * Which of the optional modules are included in the build
+ * for the most part this is for modules that need an init
+ * or power entry point.
+ *
+ * Use Defaults.
+ */
+
+/*
+ * Default FB/Display Resolution
+ */
+#define CONFIG_DEFAULT_WIDTH  640
+#define CONFIG_DEFAULT_HEIGHT 480
+#define CONFIG_DEFAULT_PF     IGD_PF_ARGB32
+
+
+/*
+  power modes supported
+  0 -don't support
+  1 - support
+
+  Use Defaults.
+*/
+
+/*
+ * Turn off fences for performance analysis. 3d makes use of "Use Fences"
+ * So this will make fences regions become linear but everything should
+ * still work.
+ *
+ * #define CONFIG_NOFENCES
+ */
+
+/* Don't enable Dynamic port driver loading for simple driver. For simple,
+ * one can limit the port drivers by enabling CONFIG_LIMIT_PDS to
+ * required port drivers *
+ *
+ * Enable Dynamic port driver loading
+ *
+ * #define IGD_DPD_ENABLED 1 */
+
+/* Enable required port drivers. */
+#define CONFIG_LIMIT_PDS 1
+#define CONFIG_PD_ANALOG 0
+#define CONFIG_PD_LVDS   1
+#define CONFIG_PD_SDVO   1
+#define CONFIG_PD_TV     0 /* Integrated TV for NAPA */
+#define CONFIG_PD_CH7036  1
+
+#define CONFIG_LINK_PD_LVDS
+#define CONFIG_LINK_PD_SDVO
+#define CONFIG_LINK_PD_CH7036
+
+#define CONFIG_DECODE
+
+#define CONFIG_ST
+
+#include <config_default.h>
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/cfg/config_default.h b/drivers/gpu/drm/emgd/emgd/cfg/config_default.h
new file mode 100644
index 0000000..18e97f5
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/cfg/config_default.h
@@ -0,0 +1,199 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: config_default.h
+ * $Revision: 1.16 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file is used in conjunction with the platform's config.h to
+ *  gererate a full set of build defines. This file should provide defaults
+ *  for defines such that a platform's config.h can include only the
+ *  minimal set of non-standard options.
+ *  Defines should be named such that:
+ *  CONFIG_<FOO>: Is defined or undefined suitable for use with ifdef and
+ *  can be used with the build system's DIRS_FOO or OBJECTS_FOO. Any
+ *  CONFIG_FOO added here must also have an entry in config_helper.c.
+ *  CONFIG_ENABLE_FOO: Should be defined always and defined to a 1 or 0.
+ *  This is suitble for use in if(CONFIG_ENABLE_FOO) and expected that
+ *  a compiler will optimize away if(0)'s.
+ *  CONFIG_LIMIT_FOO: Should prevent some default set of FOO defines
+ *  from being included. For instance CONFIG_LIMIT_MODES prevents the
+ *  long default list of default modes from being used and instead the
+ *  platform's config.h must define the requested modes manually.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _HAL_CONFIG_DEFAULT_H
+#define _HAL_CONFIG_DEFAULT_H
+
+#include <igd_version.h>
+
+#ifndef CONFIG_MICRO
+#define CONFIG_FULL
+#endif
+
+#ifndef CONFIG_LIMIT_CORES
+#define CONFIG_PLB
+#define CONFIG_TNC
+#endif /* CONFIG_LIMIT_CORES */
+
+#ifdef CONFIG_DEPRECATED
+#if 0 /* WHT Modules need some updating */
+#define CONFIG_810
+#define CONFIG_810DC
+#define CONFIG_810E
+#define CONFIG_815
+#define CONFIG_830
+#define CONFIG_835
+#define CONFIG_845
+#define CONFIG_855
+#define CONFIG_865
+#define CONFIG_915GD
+#define CONFIG_915AL
+#define	CONFIG_945G
+#define	CONFIG_945GM
+#define	CONFIG_945GME
+#define CONFIG_Q35
+#define CONFIG_965G
+#define CONFIG_965GM
+#define CONFIG_CTG
+#define CONFIG_Q45
+#define CONFIG_PNV
+#endif
+#endif
+
+#ifndef CONFIG_LIMIT_MODULES
+#define CONFIG_INIT
+#define CONFIG_REG
+#define CONFIG_POWER
+#define CONFIG_MODE
+#define CONFIG_DSP
+#define CONFIG_PI
+#define CONFIG_PD
+#define CONFIG_APPCONTEXT
+#define CONFIG_OVERLAY
+#endif /* CONFIG_LIMIT_MODULES */
+
+#ifndef CONFIG_LIMIT_PDS
+#define CONFIG_PD_ANALOG
+#define CONFIG_PD_LVDS
+#define CONFIG_PD_TV
+#define CONFIG_PD_HDMI
+#define CONFIG_PD_SDVO
+#define CONFIG_PD_SOFTPD
+#define CONFIG_PD_CH7036
+#endif
+
+#ifdef CONFIG_DEPRECATED
+#ifndef CONFIG_LIMIT_PDS
+#define CONFIG_PD_SII164
+#define CONFIG_PD_CH7009
+#define CONFIG_PD_TL955
+#define CONFIG_PD_RGBA
+#define CONFIG_PD_NS2501
+#define CONFIG_PD_TH164
+#define CONFIG_PD_FS454
+#define CONFIG_PD_NS387
+#define CONFIG_PD_CX873
+#define CONFIG_PD_FS460
+#define CONFIG_PD_CH7017
+#define CONFIG_PD_TI410
+#endif
+#endif
+
+#ifndef CONFIG_DEBUG_FLAGS
+#define CONFIG_DEBUG_FLAGS			  \
+	0, /* Command Module */			  \
+		0,	/* DSP Module */		  \
+		0,	/* Mode Module */		  \
+		0,	/* Init Module */		  \
+		0,	/* Overlay Module */	  \
+		0,	/* Power Module */		  \
+		0,	/* 2D Module */			  \
+		0,	/* Blend Module */		  \
+		0,	/* State Module */		  \
+		0,	/* GMM Module */		  \
+		0,	/* Gart Module */		  \
+		0,	/* OAL Module */		  \
+		0,	/* Interrupt Module */	  \
+		0,	/* Port Driver Module */  \
+		0,	/* Video Decode Module */ \
+		0,	/* PVR 3-Ptr Disp Drv */  \
+		0,	/* Buffer Class Module */ \
+\
+		0,	/* Global Tracing */	  \
+		0,	/* Global Instructions */ \
+		0,	/* Global Debug */		  \
+\
+		0,	/* Verbose Blend Stats */ \
+		0,	/* Verbose Overlay Dump */\
+		0,	/* Verbose Cmd Dump */	  \
+		0,	/* Verbose GMM Dump */    \
+		0	/* Verbose Shader Dump */
+
+#endif
+
+#ifndef CONFIG_DEBUG_IAL_FLAGS
+#define CONFIG_DEBUG_IAL_FLAGS 0
+#endif
+
+/* we ensure IAL's that do not support hw binning has this flag as '0' */
+#ifndef CONFIG_ENABLE_BINNING
+#define CONFIG_ENABLE_BINNING 0
+#endif
+
+#ifndef CONFIG_ENABLE_THREADS
+#define CONFIG_ENABLE_THREADS 0
+#endif
+
+
+
+/*
+ * These Meta-Defines should not be set in the config.h. They are enabled
+ * here based on more granular defines that come from config.h. For instance
+ * CONFIG_NAP should be enabled when any chips from the NAP family are enabled.
+ */
+#if defined(CONFIG_810) || defined(CONFIG_810DC) || defined(CONFIG_810E) ||\
+	defined(CONFIG_815)
+#define CONFIG_WHT
+#endif
+
+#if defined(CONFIG_830) || defined(CONFIG_835) || defined(CONFIG_845) ||\
+	defined(CONFIG_855) || defined(CONFIG_865)
+#define CONFIG_ALM
+#endif
+
+#if defined(CONFIG_915GD) || defined(CONFIG_915AL) || defined(CONFIG_945G) ||\
+	defined(CONFIG_945GM) || defined(CONFIG_945GME) || defined(CONFIG_Q35) ||\
+	defined(CONFIG_PNV)
+#define CONFIG_NAP
+#endif
+
+#if defined(CONFIG_965G) || defined(CONFIG_965GM) || \
+	defined(CONFIG_CTG) || defined(CONFIG_Q45)
+#define CONFIG_GN4
+#endif
+
+
+#endif /* _HAL_CONFIG_DEFAULT_H */
+
diff --git a/drivers/gpu/drm/emgd/emgd/cfg/config_helper.c b/drivers/gpu/drm/emgd/emgd/cfg/config_helper.c
new file mode 100644
index 0000000..d758648
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/cfg/config_helper.c
@@ -0,0 +1,244 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: config_helper.c
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#include <stdio.h>
+
+#include <config.h>
+
+int main(int argc, char **argv)
+{
+	char configs[] = ""
+#ifdef CONFIG_MICRO
+		"MICRO "
+#else
+		"FULL "
+#endif
+#ifdef CONFIG_WHT
+		"WHT "
+#endif
+#ifdef CONFIG_ALM
+		"ALM "
+#endif
+#ifdef CONFIG_NAP
+		"NAP "
+#endif
+#ifdef CONFIG_GN4
+		"GN4 "
+#endif
+#ifdef CONFIG_PLB
+		"PLB "
+#endif
+#ifdef CONFIG_TNC
+		"TNC "
+#endif
+#ifdef CONFIG_MODE
+		"MODE "
+#endif
+#ifdef CONFIG_DSP
+		"DSP "
+#endif
+#ifdef CONFIG_PI
+		"PI "
+#endif
+#ifdef CONFIG_PD
+		"PD "
+#endif
+#ifdef CONFIG_INIT
+		"INIT "
+#endif
+#ifdef CONFIG_INTERRUPT
+		"INTERRUPT "
+#endif
+#ifdef CONFIG_GART
+		"GART "
+#endif
+#ifdef CONFIG_REG
+		"REG "
+#endif
+#ifdef CONFIG_RESET
+		"RESET "
+#endif
+#ifdef CONFIG_POWER
+		"POWER "
+#endif
+#ifdef CONFIG_GMM
+		"GMM "
+#endif
+#ifdef CONFIG_MICRO_GMM
+		"MICRO_GMM "
+#endif
+#ifdef CONFIG_APPCONTEXT
+		"APPCONTEXT "
+#endif
+#ifdef CONFIG_CMD
+		"CMD "
+#endif
+#ifdef CONFIG_2D
+		"2D "
+#endif
+#ifdef CONFIG_BLEND
+		"BLEND "
+#endif
+#ifdef CONFIG_OVERLAY
+		"OVERLAY "
+#endif
+#ifdef CONFIG_DECODE
+		"DECODE "
+#endif
+		/*
+		 * Port Driver Compile Options
+		 */
+#ifdef CONFIG_PD_ANALOG
+		"PD_ANALOG "
+#endif
+#ifdef CONFIG_PD_SII164
+		"PD_SII164 "
+#endif
+#ifdef CONFIG_PD_CH7009
+		"PD_CH7009 "
+#endif
+#ifdef CONFIG_PD_TL955
+		"PD_TL955 "
+#endif
+#ifdef CONFIG_PD_RGBA
+		"PD_RGBA "
+#endif
+#ifdef CONFIG_PD_NS2501
+		"PD_NS2501 "
+#endif
+#ifdef CONFIG_PD_TH164
+		"PD_TH164 "
+#endif
+#ifdef CONFIG_PD_FS454
+		"PD_FS454 "
+#endif
+#ifdef CONFIG_PD_NS387
+		"PD_NS387 "
+#endif
+#ifdef CONFIG_PD_CX873
+		"PD_CX873 "
+#endif
+#ifdef CONFIG_PD_LVDS
+		"PD_LVDS "
+#endif
+#ifdef CONFIG_PD_FS460
+		"PD_FS460 "
+#endif
+#ifdef CONFIG_PD_CH7017
+		"PD_CH7017 "
+#endif
+#ifdef CONFIG_PD_TI410
+		"PD_TI410 "
+#endif
+#ifdef CONFIG_PD_TV
+		"PD_TV "
+#endif
+#ifdef CONFIG_PD_HDMI
+		"PD_HDMI "
+#endif
+#ifdef CONFIG_PD_SDVO
+		"PD_SDVO "
+#endif
+#ifdef CONFIG_PD_SOFTPD
+		"PD_SOFTPD "
+#endif
+#ifdef CONFIG_PD_CH7036
+		"PD_CH7036 "
+#endif	
+		/*
+		 * Port Driver Link Options
+		 */
+#ifdef CONFIG_LINK_PD_ANALOG
+		"LINK_PD_ANALOG "
+#endif
+#ifdef CONFIG_LINK_PD_SII164
+		"LINK_PD_SII164 "
+#endif
+#ifdef CONFIG_LINK_PD_CH7009
+		"LINK_PD_CH7009 "
+#endif
+#ifdef CONFIG_LINK_PD_TL955
+		"LINK_PD_TL955 "
+#endif
+#ifdef CONFIG_LINK_PD_RGBA
+		"LINK_PD_RGBA "
+#endif
+#ifdef CONFIG_LINK_PD_NS2501
+		"LINK_PD_NS2501 "
+#endif
+#ifdef CONFIG_LINK_PD_TH164
+		"LINK_PD_TH164 "
+#endif
+#ifdef CONFIG_LINK_PD_FS454
+		"LINK_PD_FS454 "
+#endif
+#ifdef CONFIG_LINK_PD_NS387
+		"LINK_PD_NS387 "
+#endif
+#ifdef CONFIG_LINK_PD_CX873
+		"LINK_PD_CX873 "
+#endif
+#ifdef CONFIG_LINK_PD_LVDS
+		"LINK_PD_LVDS "
+#endif
+#ifdef CONFIG_LINK_PD_FS460
+		"LINK_PD_FS460 "
+#endif
+#ifdef CONFIG_LINK_PD_CH7017
+		"LINK_PD_CH7017 "
+#endif
+#ifdef CONFIG_LINK_PD_TI410
+		"LINK_PD_TI410 "
+#endif
+#ifdef CONFIG_LINK_PD_TV
+		"LINK_PD_TV "
+#endif
+#ifdef CONFIG_LINK_PD_HDMI
+		"LINK_PD_HDMI "
+#endif
+#ifdef CONFIG_LINK_PD_SDVO
+		"LINK_PD_SDVO "
+#endif
+#ifdef CONFIG_LINK_PD_SOFTPD
+		"LINK_PD_SOFTPD "
+#endif
+#ifdef CONFIG_LINK_PD_CH7036
+      "LINK_PD_CH7036 "
+#endif
+
+#ifdef CONFIG_COPP
+		"COPP "
+#endif
+		;
+	printf("%s\n", configs);
+	return 0;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_global.c b/drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_global.c
new file mode 100644
index 0000000..52bc62e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_global.c
@@ -0,0 +1,34 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_global.c
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+#include <config.h>
+#include <igd_debug.h>
+
+/* Global debug flag has been moved to egd_drm/emgd/drm/emgd_drv.c */
diff --git a/drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_init.c b/drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_init.c
new file mode 100644
index 0000000..335a796
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/core/init/cmn/igd_init.c
@@ -0,0 +1,918 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_init.c
+ * $Revision: 1.24 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains the implementation of the core init module. It
+ *  is responsible from initializing the HAL and the device and gathering
+ *  all necessary general device information. This module is partially
+ *  optional such that portions may be disabled to save code space.
+ *  When CONFIG_MICRO is enabled:
+ *  Firmware parameters are NOT read.
+ *  Only the first device instance is queried and configured.
+ *  Revision ID is NOT queried, it is assumed to be 0.
+ *  MMIO regions are not discovered or mapped.
+ *  FB memory is not discovered or mapped.
+ *  Shutdown is a no-op.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.init
+
+#include <io.h>
+#include <pci.h>
+#include <memory.h>
+#include <memmap.h>
+
+#include <igd_init.h>
+#include <igd_pwr.h>
+#include <igd_errno.h>
+#include <igd_mode.h>
+#include <igd_debug.h>
+
+#include <context.h>
+#include <cmd.h>
+#include <reset.h>
+#include <dsp.h>
+#include <utils.h>
+#include <general.h>
+#include <intelpci.h>
+#include <mode_access.h>
+#include <module_init.h>
+#include <mode.h>
+
+#include "init_dispatch.h"
+
+/* OAL header */
+#include <sched.h>
+
+/*!
+ * @addtogroup core_group
+ * @{
+ */
+
+
+unsigned long _sgx_base, _msvdx_base, _topaz_base;
+
+/* Notes: If the bus is of value 0xFFFF, then the particular
+ * device is searched for in the whole PCI topology
+ */
+typedef struct _iegd_pci {
+	unsigned short vendor_id;
+	unsigned short device_id;
+	unsigned short bus;
+	unsigned short dev;
+	unsigned short func;
+} iegd_pci_t;
+
+static iegd_pci_t intel_pci_device_table[] = {
+#ifdef CONFIG_810
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_810, 0, 2, 0},
+#endif
+#ifdef CONFIG_810DC
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_810DC, 0, 2, 0},
+#endif
+#ifdef CONFIG_810E
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_810E, 0, 2, 0},
+#endif
+#ifdef CONFIG_815
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_815, 0, 2, 0},
+#endif
+#ifdef CONFIG_855
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_855, 0, 2, 0},
+#endif
+#ifdef CONFIG_830
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_830M, 0, 2, 0},
+#endif
+#ifdef CONFIG_835
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_835, 0, 2, 0},
+#endif
+#ifdef CONFIG_845
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_845G, 0, 2, 0},
+#endif
+#ifdef CONFIG_865
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_865G, 0, 2, 0},
+#endif
+#ifdef CONFIG_915GD
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_915GD, 0, 2, 0},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_910GL, 0, 2, 0},
+#endif
+#ifdef CONFIG_915AL
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_915AL, 0, 2, 0},
+#endif
+#ifdef CONFIG_945G
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_945G, 0, 2, 0},
+#endif
+#ifdef CONFIG_945GM
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_945GM, 0, 2, 0},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_945GME, 0, 2, 0},
+#endif
+#ifdef CONFIG_Q35
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_Q35, 0, 2, 0},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_Q35A2, 0, 2, 0},
+#endif
+#ifdef CONFIG_965G
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_965G, 0, 2, 0},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_G965, 0, 2, 0},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_Q965, 0, 2, 0},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_946GZ, 0, 2, 0},
+#endif
+#ifdef CONFIG_965GM
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_GME965, 0, 2, 0},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_GM965, 0, 2, 0},
+#endif
+#ifdef CONFIG_CTG
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_CTG, 0, 2, 0},
+#endif
+#ifdef CONFIG_PLB
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_PLB, 0, 2, 0},
+#endif
+#ifdef CONFIG_TNC
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_TNC, 0, 2, 0},
+#ifdef CONFIG_MSRT
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_TNC_A0, 0, 2, 0},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_LNC, 0, 2, 0},
+#endif
+#endif
+#ifdef CONFIG_Q45
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_ELK, 0, 2, 0},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_Q45, 0, 2, 0},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_G45, 0, 2, 0},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_VGA_G41, 0, 2, 0},
+#endif
+
+};
+
+
+/*
+ * On platforms with multiple PCI devices (currently only Atom E6xx), we
+ * need to disable legacy VGA decoding on the second device, otherwise
+ * the VGA arbiter will prevent DRI from being used.  Keep a list of
+ * devices we need to disable this on.
+ */
+static iegd_pci_t disabled_legacy_vga_list[] = {
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_SDVO_TNC, 0, 0, 0},
+};
+
+#define MAX_PCI_DEVICE_SUPPORTED \
+	(sizeof(intel_pci_device_table)/sizeof(intel_pci_device_table[0]))
+#define MAX_LEGACY_VGA_DISABLE \
+	(sizeof(disabled_legacy_vga_list)/sizeof(disabled_legacy_vga_list[0]))
+
+
+static dispatch_table_t init_dispatch_table[] = {
+
+	DISPATCH_PLB(&init_dispatch_plb)
+	DISPATCH_TNC(&init_dispatch_tnc)
+#ifdef CONFIG_MSRT
+	DISPATCH_TNC_A0(&init_dispatch_tnc_a0)
+	DISPATCH_LNC(&init_dispatch_lnc)
+#endif
+	DISPATCH_END
+};
+
+
+
+static init_dispatch_t *init_dispatch;
+
+
+/*---------------------------------------------------------------------------
+ * Optional Init Module Components
+ *--------------------------------------------------------------------------*/
+#ifndef CONFIG_MICRO
+
+/*!
+ * This function allows for calling the igd_get_param function with a
+ * display handle instead of a driver handle. This version is exported in
+ * the dispatch table.
+ *
+ * @param display_handle
+ * @param id
+ * @param value
+ *
+ * @return igd_get_param()
+ */
+static int _igd_get_param(igd_display_h display_handle,
+	unsigned long id,
+	unsigned long *value)
+{
+	igd_display_context_t *display = (igd_display_context_t *)display_handle;
+	return igd_get_param((igd_driver_h)display->context, id, value);
+}
+
+/*!
+ * This function allows for calling the igd_set_param function with a
+ * display handle instead of a driver handle. This version is exported in
+ * the dispatch table.
+ *
+ * @param display_handle
+ * @param id
+ * @param value
+ *
+ * @return igd_set_param()
+ */
+static int _igd_set_param(igd_display_h display_handle,
+	unsigned long id,
+	unsigned long value)
+{
+	igd_display_context_t *display = (igd_display_context_t *)display_handle;
+	return igd_set_param((igd_driver_h)display->context, id, value);
+}
+
+/*!
+ * This function should never be called directly. It comprises the optional
+ * portion of the igd_set_param function which should be used instead.
+ *
+ * @param context
+ * @param id
+ * @param value
+ *
+ * @return set_param()
+ * @return 0
+ */
+static int _init_set_param(igd_context_t *context,
+	unsigned long id,
+	unsigned long value)
+{
+
+	switch(id) {
+	case IGD_PARAM_DEBUG_MASK:
+		*((unsigned long *)emgd_debug) = value;
+		break;
+	default:
+		return init_dispatch->set_param(context, id, value);
+	}
+
+	return 0;
+}
+
+/*!
+ * This function should never be called directly. It comprises the optional
+ * portion of the igd_get_param function which should be used instead.
+ *
+ * @param display_handle
+ * @param id
+ * @param value
+ *
+ * @return set_param()
+ * @return 0
+ */
+static int _init_get_param(igd_display_h display_handle,
+	unsigned long id,
+	unsigned long *value)
+{
+	switch(id) {
+	case IGD_PARAM_DEBUG_MASK:
+		*value = *((unsigned long *)emgd_debug);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+/*!
+ * Hook up the dispatch pointers. These are only available when the
+ * full init module is compiled in.
+ *
+ * @param context
+ *
+ * @return void
+ */
+static void _init_dispatch(igd_context_t *context)
+{
+	/* Hook up top level dispatch table functions owner by init */
+	context->dispatch.get_param           = _igd_get_param;
+	context->dispatch.set_param           = _igd_set_param;
+	return;
+}
+
+/*!
+ * Shutdown all modules in the required order. Optional modules must
+ * only be called if they exist.
+ *
+ * @param context
+ *
+ * @return void
+ */
+static void shutdown_modules(igd_context_t *context)
+{
+	EMGD_TRACE_ENTER;
+
+	if(context->mod_dispatch.shutdown_2d) {
+		context->mod_dispatch.shutdown_2d(context);
+	}
+	if(context->mod_dispatch.blend_shutdown) {
+		context->mod_dispatch.blend_shutdown(context);
+	}
+	if(context->mod_dispatch.interrupt_shutdown) {
+		context->mod_dispatch.interrupt_shutdown(context);
+	}
+	if(context->mod_dispatch.appcontext_shutdown) {
+		context->mod_dispatch.appcontext_shutdown(context);
+	}
+	if(context->mod_dispatch.reset_shutdown) {
+		context->mod_dispatch.reset_shutdown(context);
+	}
+	if(context->mod_dispatch.mode_shutdown) {
+		context->mod_dispatch.mode_shutdown(context);
+	}
+	if(context->mod_dispatch.pwr_shutdown) {
+		context->mod_dispatch.pwr_shutdown(context);
+	}
+	if(context->mod_dispatch.overlay_shutdown) {
+		context->mod_dispatch.overlay_shutdown(context);
+	}
+	if(context->mod_dispatch.cmd_shutdown) {
+		context->mod_dispatch.cmd_shutdown(context);
+	}
+	/*
+	 * GMM is not optional shutdown must exist.
+	 */
+	gmm_shutdown(context);
+
+	/*
+	 * Reg module must be last to restore the state of the device to the
+	 * way it was before the driver started.
+	 */
+	EMGD_DEBUG("post reg_shutdown: %p", context->mod_dispatch.reg_shutdown);
+	if(context->mod_dispatch.reg_shutdown) {
+		context->mod_dispatch.reg_shutdown(context);
+	}
+
+	EMGD_TRACE_EXIT;
+}
+
+#endif
+
+/*!
+ * Empty idle function. This insures that anyone can call
+ * dispatch->idle() in any configuration. If there is a command
+ * module this will get replaced with a real idle function.
+ *
+ * @param driver_handle
+ *
+ * @return 0
+ */
+static int empty_idle(igd_driver_h driver_handle)
+{
+	return 0;
+}
+
+/*!
+ * Empty sync function. This insures that anyone can call
+ * dispatch->sync() in any configuration.
+ *
+ * @param display_handle pointer to an IGD_DISPLAY pointer returned
+ *    from a successful call to dispatch->alter_displays().
+ *
+ * @param priority The command queue to use. IGD_PRIORITY_NORMAL is
+ *    correct for most circumstances.
+ *
+ * @param sync The sync identifier that will be populated and returned
+ *    during the call. To insert a new sync, this should be passed
+ *    containing 0 (A pointer to a zero). To check the status of an
+ *    existing sync pass the value returned from a previous call to
+ *    this function.
+ *
+ * @param flags Sync flags.
+ *
+ * @returns
+ *   0: On Success
+ *   -IGD_ERROR_BUSY: When the sync is not yet complete
+ */
+static int empty_sync(igd_display_h display_handle, int priority,
+		unsigned long *sync, unsigned long flags)
+{
+	return 0;
+}
+
+/*!
+ * Non-Optional Init Module Components
+ *
+ * @param found_device
+ * @param pdev
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_NODEV on failure
+ */
+static int detect_device(iegd_pci_t **found_device,
+	os_pci_dev_t *pdev)
+{
+	int i;
+
+	/* Scan the PCI bus for supported device */
+	for(i = 0; i < MAX_PCI_DEVICE_SUPPORTED; i++) {
+
+		*pdev = OS_PCI_FIND_DEVICE(intel_pci_device_table[i].vendor_id,
+			intel_pci_device_table[i].device_id,
+			intel_pci_device_table[i].bus,
+			intel_pci_device_table[i].dev,
+			intel_pci_device_table[i].func,
+			(os_pci_dev_t)0);
+
+		if(*pdev) {
+			*found_device = &intel_pci_device_table[i];
+			break;
+		}
+	}
+	if(!*pdev) {
+		EMGD_ERROR("No supported VGA devices found.");
+		return -IGD_ERROR_NODEV;
+	}
+
+	EMGD_DEBUG("VGA device found: 0x%x", (*found_device)->device_id);
+
+	return 0;
+}
+
+/* This is currently a global context, because the context is needed
+ * in io.c for vbios in OS_READx and OS_WRITEx functions. */
+igd_context_t *fixme_vbios_context;
+
+/* By declaring io_mapped and io_base as globals, we no longer need to
+ * include context.h in the vbios common io.c */
+
+/* Device 0:2:0 io_base */
+unsigned char io_mapped;      /* True for io mapped MMIO space */
+unsigned short io_base;
+
+/* Device 0:2:0 [VGA device] io_base */
+unsigned char io_mapped_lvds; /* True for io mapped MMIO space */
+unsigned short io_base_lvds;
+
+/* Device 0:3:0 [SDVO device] io_base */
+unsigned char io_mapped_sdvo; /* True for io mapped MMIO space */
+unsigned short io_base_sdvo;
+
+/* Device 0:31:0 [LPC device] io_base */
+unsigned char io_mapped_lpc; /* True for io mapped MMIO space */
+unsigned short io_base_lpc;
+
+/* Device 6:0:1 [STMicro SDVO device] io_base */
+unsigned char io_mapped_sdvo_st; /* True for io mapped MMIO space */
+unsigned short io_base_sdvo_st;
+unsigned char io_mapped_sdvo_st_gpio; /* True for io mapped MMIO space */
+unsigned short io_base_sdvo_st_gpio;
+
+
+/*!
+ * This function is directly exported.
+ *
+ * @param found_device
+ * @param pdev
+ *
+ * @return igd_driver_h
+ * @return NULL on failure
+ */
+igd_driver_h igd_driver_init( igd_init_info_t *init_info )
+{
+	igd_context_t *context;
+	os_pci_dev_t pdev = (os_pci_dev_t)NULL;
+	os_pci_dev_t vga_disable_dev;
+	iegd_pci_t *found_device;
+	int ret;
+	int i;
+
+	EMGD_TRACE_ENTER;
+
+	/* Allocate a context */
+	context = (void *) OS_ALLOC(sizeof(igd_context_t));
+	fixme_vbios_context = context;
+	if(!context) {
+		EMGD_ERROR_EXIT("igd_driver_init failed to create context");
+		return NULL;
+	}
+	OS_MEMSET(context, 0, sizeof(igd_context_t));
+
+	/* Search VGA devices for a supported one */
+	ret = detect_device(&found_device, &pdev);
+	if(ret) {
+		OS_FREE(context);
+		return NULL;
+	}
+
+	/*
+	 * Some platforms (currently only Atom E6xx) use two PCI devices (the
+	 * second device being for SDVO) and this causes the VGA arbiter to get
+	 * involved.  Legacy VGA decoding must be disabled for all PCI devices
+	 * except one, otherwise the VGA arbiter will prevent DRI usage in the
+	 * X server.
+	 */
+	for (i = 0; i < MAX_LEGACY_VGA_DISABLE; i++) {
+		vga_disable_dev = os_pci_find_device(PCI_VENDOR_ID_INTEL,
+				PCI_DEVICE_ID_SDVO_TNC, 0xFFFF, 0, 0, NULL);
+		if (vga_disable_dev) {
+			printk(KERN_INFO "VGA arbiter detected; disabling legacy VGA"
+					" decoding on SDVO device\n");
+			os_pci_disable_legacy_vga_decoding(vga_disable_dev);
+			os_pci_free_device(vga_disable_dev);
+		}
+	}
+
+	context->device_context.did = found_device->device_id;
+	init_dispatch = (init_dispatch_t *)dispatch_acquire(context,
+		init_dispatch_table);
+
+	if(!init_dispatch) {
+		EMGD_ERROR_EXIT("No dispatch found for listed device");
+		return NULL;
+	}
+
+	ret = init_dispatch->query(context, init_dispatch, pdev, &init_info->bus,
+		&init_info->slot, &init_info->func);
+	if(ret) {
+		OS_FREE(context);
+		EMGD_ERROR_EXIT("Device Dependent Query Failed");
+		return NULL;
+	}
+
+	/* init info */
+	init_info->vendor_id = found_device->vendor_id;
+	init_info->device_id = found_device->device_id;
+	init_info->name = init_dispatch->name;
+	init_info->chipset = init_dispatch->chipset;
+	init_info->default_pd_list = init_dispatch->default_pd_list;
+
+	EMGD_TRACE_EXIT;
+
+	return (igd_driver_h)context;
+}
+
+/*!
+ * This function is directly exported.
+ *
+ * @param driver_handle
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int igd_driver_config(igd_driver_h driver_handle)
+{
+	igd_context_t *context = (igd_context_t *)driver_handle;
+	int ret;
+
+	EMGD_TRACE_ENTER;
+
+	EMGD_ASSERT(context, "Null context!", -IGD_ERROR_INVAL);
+
+	ret = init_dispatch->config(context, init_dispatch);
+	if(ret) {
+		EMGD_ERROR_EXIT("Device Dependent Config Failed");
+		return ret;
+	}
+
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ * Initialize modules in the required order. Optional modules must be called
+ * with their initalization macro to ensure that they are not called when
+ * their option is not enabled.
+ *
+ * @param params
+ * @param context
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+/* FIXME: All modules should get params from mod_dispatch */
+static int init_modules(igd_param_t *params, igd_context_t *context)
+{
+	unsigned int ret;
+
+	EMGD_TRACE_ENTER;
+
+	/*
+	 * Reg module must be first so that the state of the device can be
+	 * saved before anything else is touched.
+	 */
+	ret = REG_INIT(context, (params->preserve_regs)?IGD_DRIVER_SAVE_RESTORE:0);
+	if (ret) {
+		EMGD_DEBUG("Error initializing register module");
+	}
+
+	/*
+	 *  GMM is not optional. Its init function must exist.
+	 */
+	ret = gmm_init(context, params->page_request, params->max_fb_size);
+	if(ret) {
+		EMGD_ERROR_EXIT("GMM Module Init Failed");
+		return ret;
+	}
+
+	ret = CMD_INIT(context);
+	if(ret) {
+		EMGD_ERROR_EXIT("Command Module Init Failed");
+		return ret;
+	}
+
+	/*
+	 *  Mode is not optional. Its init function must exist.
+	 */
+	ret = mode_init(context);
+	if (ret) {
+		EMGD_ERROR_EXIT("Mode Module Init Failed");
+		return ret;
+	}
+
+	ret = APPCONTEXT_INIT(context);
+	if (ret) {
+		EMGD_ERROR_EXIT("Appcontext Module Init Failed");
+		return ret;
+	}
+
+	ret = OVERLAY_INIT(context, params);
+	if(ret) {
+		EMGD_ERROR_EXIT("Overlay Module Init Failed");
+		return ret;
+	}
+
+	ret = PWR_INIT(context);
+	if(ret) {
+		EMGD_DEBUG("Error initializing power module");
+	}
+
+	ret = RESET_INIT(context);
+	if(ret) {
+		EMGD_DEBUG("Error initializing reset module");
+	}
+
+	ret = OS_INIT_INTERRUPT(context->device_context.did,
+		context->device_context.virt_mmadr);
+	if(ret) {
+		EMGD_ERROR_EXIT("Interrupt Module Init Failed");
+		return ret;
+	}
+
+	ret = BLEND_INIT(context);
+	if(ret) {
+		EMGD_DEBUG("Error initializing blend module");
+	}
+
+	ret = INIT_2D(context);
+	if(ret) {
+		EMGD_DEBUG("Error initializing 2d module");
+	}
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ * This function is directly exported.
+ *
+ * @param driver_handle
+ * @param dsp
+ * @param params
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int igd_module_init(igd_driver_h driver_handle,
+	igd_dispatch_t **dsp,
+	igd_param_t *params)
+{
+	igd_context_t *context = (igd_context_t *)driver_handle;
+	device_context_t *device;
+	int ret = 0;
+
+	EMGD_TRACE_ENTER;
+
+	device = &context->device_context;
+	context->device_context.power_state = IGD_POWERSTATE_D0;
+	context->mod_dispatch.init_params = params;
+	context->dispatch.idle = empty_idle;
+	context->dispatch.sync = empty_sync;
+	context->mod_dispatch.in_dih_clone_mode = 0;
+	context->mod_dispatch.dih_clone_display = 0;
+	context->mod_dispatch.fb_blend_ovl_override = 0;
+
+	/* Intialize IGD Modules */
+	ret = init_modules(params, context);
+	if (ret) {
+		EMGD_ERROR_EXIT("Init Modules Failed");
+		return ret;
+	}
+
+	OPT_MICRO_VOID_CALL(_init_dispatch(context));
+
+	*dsp = &context->dispatch;
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ * This function is directly exported.
+ *
+ * @param driver_handle
+ * @param info
+ *
+ * @return 0
+ */
+int igd_get_config_info(igd_driver_h driver_handle,
+	igd_config_info_t *config_info)
+{
+	igd_context_t *context = (igd_context_t *)driver_handle;
+
+	EMGD_TRACE_ENTER;
+
+	EMGD_ASSERT(context, "Null context!", -IGD_ERROR_INVAL);
+	EMGD_ASSERT(config_info, "Null config_info!", -IGD_ERROR_INVAL);
+
+	OS_MEMSET(config_info, 0, sizeof(igd_config_info_t));
+
+	/* Config information already obtained from driver_config() */
+	config_info->mmio_base_phys = context->device_context.mmadr;
+	config_info->mmio_base_virt = context->device_context.virt_mmadr;
+	config_info->gtt_memory_base_phys = context->device_context.fb_adr;
+	/* config_info->gtt_memory_base_virt = context->device_context.virt_fb_adr; */
+	config_info->gtt_memory_size = context->device_context.mem_size;
+	config_info->revision_id = context->device_context.rid;
+	config_info->hw_status_offset = context->device_context.hw_status_offset;
+	config_info->stolen_memory_base_virt = 0; /* FIXME: remove this */
+
+	/* get the portions held in the dsp module */
+	if(context->mod_dispatch.dsp_get_config_info) {
+		context->mod_dispatch.dsp_get_config_info(context, config_info);
+	}
+	/* get the portions held in the pi module */
+	if(context->mod_dispatch.pi_get_config_info) {
+		context->mod_dispatch.pi_get_config_info(context, config_info);
+	}
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ * This function is directly exported. When compiled without the init
+ * module the function calls the DD layer get_param function. When the
+ * full init module is included this function calls _init_get_param to
+ * first get the DI parameters then calls the DD layer.
+ *
+ * @param driver_handle
+ * @param id
+ * @param value
+ *
+ * @return get_param()
+ */
+int igd_get_param(igd_driver_h driver_handle,
+	unsigned long id,
+	unsigned long *value)
+{
+	igd_context_t *context = (igd_context_t *)driver_handle;
+
+	EMGD_ASSERT(context, "Null Driver Handle", -IGD_ERROR_INVAL);
+	EMGD_ASSERT(value, "Null Value", -IGD_ERROR_INVAL);
+
+	OPT_MICRO_CALL(_init_get_param(driver_handle, id, value));
+
+	return init_dispatch->get_param(context, id, value);
+}
+
+/*!
+ * This function is directly exported. When compiled without the init
+ * module the function does nothing and returns 0. When the full init
+ * module is included this function calls _init_set_param and returns
+ * the result.
+ *
+ * @param driver_handle
+ * @param id
+ * @param value
+ *
+ * @return 0
+ */
+int igd_set_param(igd_driver_h driver_handle,
+	unsigned long id,
+	unsigned long value)
+{
+	igd_context_t *context = (igd_context_t *)driver_handle;
+
+	EMGD_ASSERT(context, "Null Driver Handle", -IGD_ERROR_INVAL);
+
+	OPT_MICRO_CALL(_init_set_param(context, id, value));
+	return 0;
+}
+
+/*!
+ * This function is exported directly. It will shutdown an instance
+ * of the HAL that was initialized with igd_driver_init.
+ *
+ * Since the symbol is exported as part of the documented API it must
+ * always exist, however it becomes an empty function when the init
+ * module is not fully included.
+ *
+ * @param driver_handle
+ *
+ * @return void
+ */
+void igd_driver_shutdown(igd_driver_h driver_handle)
+{
+	igd_context_t *context = (igd_context_t *)driver_handle;
+
+	EMGD_TRACE_ENTER;
+
+	EMGD_ASSERT(context, "Null Driver Handle", );
+
+
+	/* Shutdown the device context */
+	init_dispatch->shutdown(context);
+
+	/* release the driver's context */
+	if(context) {
+		EMGD_DEBUG("Freeing context");
+		OS_FREE(context);
+	}
+
+	EMGD_TRACE_EXIT;
+	return;
+}
+
+/*!
+ * This function is exported. It will shutdown most of the display
+ * functions.
+ *
+ * @param driver_handle
+ *
+ * @return void
+ */
+void igd_driver_shutdown_hal(igd_driver_h driver_handle)
+{
+	igd_context_t *context = (igd_context_t *)driver_handle;
+
+	EMGD_TRACE_ENTER;
+
+	EMGD_ASSERT(context, "Null Driver Handle", );
+
+	if(context->device_context.power_state != IGD_POWERSTATE_D0) {
+		return;
+	}
+
+	/* Shutdown Modules */
+	shutdown_modules(context);
+
+	EMGD_TRACE_EXIT;
+	return;
+}
+
+
+/*!
+ * This function is exported directly. It will shutdown an instance
+ * of the HAL that was initialized with igd_driver_init.
+ *
+ * Since the symbol is exported as part of the documented API it must
+ * always exist, however it becomes an empty function when the init
+ * module is not fully included.
+ *
+ * @param driver_handle
+ *
+ * @return void
+ */
+void igd_query_2d_caps_hwhint(igd_driver_h driver_handle, 
+		unsigned long caps_val,
+		unsigned long *status)
+{
+	igd_context_t *context = (igd_context_t *)driver_handle;
+	
+	EMGD_TRACE_ENTER;
+
+	if (init_dispatch->query_2d_caps_hwint != NULL){
+		init_dispatch->
+			query_2d_caps_hwint(context, caps_val, status);
+	}
+
+	EMGD_TRACE_EXIT;
+	return;
+}
+/*----------------------------------------------------------------------------
+ * File Revision History
+ * $Id: igd_init.c,v 1.24 2011/09/30 07:53:25 rlim Exp $
+ * $Source: /nfs/fm/proj/eia/cvsroot/koheo/linux/egd_drm/emgd/core/init/cmn/igd_init.c,v $
+ *----------------------------------------------------------------------------
+ */
diff --git a/drivers/gpu/drm/emgd/emgd/core/init/cmn/init_dispatch.h b/drivers/gpu/drm/emgd/emgd/core/init/cmn/init_dispatch.h
new file mode 100644
index 0000000..7c58997
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/core/init/cmn/init_dispatch.h
@@ -0,0 +1,65 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: init_dispatch.h
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _INIT_DISPATCH_H
+#define _INIT_DISPATCH_H
+
+#include <pci.h>
+
+#include <dispatch.h>
+
+/*
+ * Note: Platforms extend this data structure so the pointer can be used
+ * as either this DI dispatch or cast to the DD dipatch.
+ */
+typedef struct _init_dispatch {
+	char *name;
+	char *chipset;
+	char *default_pd_list;
+	int (*query)(igd_context_t *context, struct _init_dispatch *dispatch,
+		os_pci_dev_t vga_dev, unsigned int *bus, unsigned int *slot,
+		unsigned int *func);
+	int (*config)(igd_context_t *context, struct _init_dispatch *dispatch);
+	int (*set_param)(igd_context_t *context, unsigned long id,
+		unsigned long value);
+	int (*get_param)(igd_context_t *context, unsigned long id,
+		unsigned long *value);
+	void (*shutdown)(igd_context_t *context);
+	int (*query_2d_caps_hwint) (igd_context_t *context,
+		unsigned long caps_val, unsigned long *status);
+} init_dispatch_t;
+
+extern init_dispatch_t init_dispatch_plb;
+extern init_dispatch_t init_dispatch_tnc;
+extern init_dispatch_t init_dispatch_tnc_a0;
+extern init_dispatch_t init_dispatch_lnc;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/core/init/plb/init_plb.c b/drivers/gpu/drm/emgd/emgd/core/init/plb/init_plb.c
new file mode 100644
index 0000000..d6a92ac
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/core/init/plb/init_plb.c
@@ -0,0 +1,458 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: init_plb.c
+ * $Revision: 1.19 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.init
+
+#include <io.h>
+#include <pci.h>
+#include <memmap.h>
+#include <gart.h>
+
+#include <memory.h>
+#include <igd.h>
+#include <igd_errno.h>
+#include <igd_init.h>
+#include <igd_gart.h>
+
+#include <context.h>
+#include <intelpci.h>
+#include <general.h>
+
+#include <plb/regs.h>
+#include <plb/context.h>
+
+#include "../cmn/init_dispatch.h"
+#include "/usr/include/linux/pci_regs.h"
+/*!
+ * @addtogroup core_group
+ * @{
+ */
+
+static int bus_master_enable_plb(platform_context_plb_t *platform_context);
+static int full_config_vga_plb(igd_context_t *context,
+	init_dispatch_t *dispatch);
+static int get_stolen_mem_plb(igd_context_t *context, unsigned long *pages);
+
+int full_get_param_plb(igd_context_t *context,
+	unsigned long id,
+	unsigned long *value);
+
+/*!
+ *
+ * @param context
+ * @param dispatch
+ * @param vga_dev
+ *
+ * @return -IGD_ERROR_NODEV on failure
+ * @return 0 on success
+ */
+int get_revision_id_plb(igd_context_t *context,
+	os_pci_dev_t vga_dev)
+{
+	EMGD_TRACE_ENTER;
+
+	/* Read RID */
+	if(OS_PCI_READ_CONFIG_8(vga_dev, PCI_RID,
+			(unsigned char *)&context->device_context.rid)) {
+		EMGD_ERROR_EXIT("Error occured reading RID");
+		return -IGD_ERROR_NODEV;
+	}
+
+	EMGD_DEBUG(" rid = 0x%lx", context->device_context.rid);
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param dispatch
+ *
+ * @return 1 on failure
+ * @return 0 on success
+ */
+int full_config_plb(igd_context_t *context,
+	init_dispatch_t *dispatch)
+{
+	unsigned long /* FIXME - reserved_mem, */ graphics_frequency ;
+	platform_context_plb_t *platform_context;
+	int ret;
+
+	EMGD_TRACE_ENTER;
+
+	platform_context = (platform_context_plb_t *)context->platform_context;
+
+	_sgx_base = 0x40000;
+	_msvdx_base = 0x50000;
+
+	/*
+	 * Enable bus mastering for platforms whose BIOS did not perform this
+	 * task for us.
+	 */
+	ret = bus_master_enable_plb(platform_context);
+	if(ret) {
+		EMGD_ERROR("Error: Enabling bus master");
+	}
+
+	/* Config VGA */
+	ret = full_config_vga_plb(context, dispatch);
+	if(ret) {
+		EMGD_ERROR_EXIT("Config VGA Failed");
+		return ret;
+	}
+
+	get_stolen_mem_plb(context, &context->device_context.reserved_mem);
+
+#if 0 /* FIXME - WHY IS THIS RETURNING 0 AND SETTING reserved_mem TO 0 ALSO? */
+	/* Get mem reservation param if it exists */
+	if(!full_get_param_plb(context, IGD_PARAM_MEM_RESERVATION,
+			&reserved_mem)) {
+		context->device_context.reserved_mem = reserved_mem;
+	}
+#endif
+
+	/* Get graphics frequency param if it exists */
+	if(!full_get_param_plb(context, IGD_PARAM_GFX_FREQ,
+			&graphics_frequency)) {
+		context->device_context.gfx_freq = (unsigned short)graphics_frequency;
+	}
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ *
+ * @param platform_context
+ *
+ * @return -1 on failure
+ * @return 0 on success
+ */
+static int bus_master_enable_plb(platform_context_plb_t *platform_context){
+	int ret;
+	unsigned char tmp;
+
+	EMGD_TRACE_ENTER;
+
+	ret = OS_PCI_READ_CONFIG_8(platform_context->pcidev0, PCI_COMMAND_MASTER, &tmp);
+	if(ret) {
+		EMGD_ERROR_EXIT("PCI read of bus master");
+		return -1;
+	}
+
+	/*
+	 * Get Bit 2, 1, and 0 and see if it is == 1
+	 * all 3 bits has to be enabled. This is to enable register read/write
+	 * in the case of a PCI card being added
+	 */
+	if((tmp & 0x7) != 0x7 ) {
+
+		tmp |= 0x7;
+		ret = OS_PCI_WRITE_CONFIG_8(platform_context->pcidev0, PCI_COMMAND_MASTER, tmp);
+		if(ret) {
+			EMGD_ERROR_EXIT("PCI write of bus master");
+			return -1;
+		}
+	}
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param dispatch
+ *
+ * @return -IGD_ERROR_NODEV on failure
+ * @return 0 on success
+ */
+static int full_config_vga_plb(igd_context_t *context,
+	init_dispatch_t *dispatch)
+{
+	platform_context_plb_t *platform_context =
+		(platform_context_plb_t *)context->platform_context;
+
+	EMGD_TRACE_ENTER;
+
+	if(OS_PCI_READ_CONFIG_32(platform_context->pcidev0,
+			PLB_PCI_MMADR, (void*)&context->device_context.mmadr)) {
+		EMGD_ERROR_EXIT("Reading MMADR");
+		return -IGD_ERROR_NODEV;
+	}
+
+	context->device_context.mmadr &= 0xfffffff9;
+	context->device_context.virt_mmadr =
+		OS_MAP_IO_TO_MEM_NOCACHE(context->device_context.mmadr, PLB_MMIO_SIZE);
+
+	if (!context->device_context.virt_mmadr) {
+		EMGD_ERROR_EXIT("Failed to map MMADR");
+		return -IGD_ERROR_NODEV;
+	}
+
+	EMGD_DEBUG("mmadr mapped %dKB @           (phys):0x%lx (virt):%p",
+		PLB_MMIO_SIZE/1024,
+		context->device_context.mmadr,
+		context->device_context.virt_mmadr);
+
+	/* PCI Interrupt Line */
+	if(OS_PCI_READ_CONFIG_8(platform_context->pcidev0,
+			PCI_INTERRUPT_LINE, (void*)&platform_context->irq)) {
+		platform_context->irq = 0;
+	}
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ * Get the # of pages used for video memory. This does not use information from
+ * the scratch register, since this is done later if it exists.
+ *
+ * @param context
+ * @param pages
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+static int get_stolen_mem_plb(igd_context_t *context, unsigned long *pages)
+{
+	platform_context_plb_t *platform_context;
+	os_pci_dev_t           vga_dev;
+	unsigned short         gmch_ctl;
+	unsigned long          stolen_mem; /* in bytes */
+	int ret;
+
+	EMGD_TRACE_ENTER;
+
+	platform_context = (platform_context_plb_t *)context->platform_context;
+	vga_dev = platform_context->pcidev0;
+
+	ret = OS_PCI_READ_CONFIG_16(vga_dev, PLB_PCI_GC, &gmch_ctl);
+	if (ret) {
+		EMGD_ERROR_EXIT("Unable to read PLB_PCI_GC");
+		return -IGD_ERROR_INVAL;
+	}
+
+	switch (gmch_ctl & 0x70) {
+	case 0x00:
+		stolen_mem = 0;
+		break;
+	case 0x10:
+		/* 1M */
+		stolen_mem = 1*1024*1024;
+		break;
+	case 0x20:
+		/* 4M */
+		stolen_mem = 4*1024*1024;
+		break;
+	case 0x30:
+		/* 8M */
+		stolen_mem = 8*1024*1024;
+		break;
+	case 0x40:
+		/* 16M */
+		stolen_mem = 16*1024*1024;
+		break;
+	case 0x50:
+		/* 32M */
+		stolen_mem = 32*1024*1024;
+		break;
+	case 0x60:
+		/* 48M */
+		stolen_mem = 48*1024*1024;
+	case 0x70:
+		/* 64M */
+		stolen_mem = 64*1024*1024;
+		break;
+	default:
+		EMGD_ERROR_EXIT("Unknown Stolen Memory Size");
+		return -IGD_ERROR_INVAL;
+	}
+
+	if (stolen_mem) {
+		/*
+		 * Subtract off the size of the GTT which is
+		 * (number of entries in DWORDS) * 4 to get it into bytes
+		 */
+		stolen_mem -= context->device_context.gatt_pages*4;
+		/* Subtract off 1 page for the scratch page */
+		stolen_mem -= 4*1024;
+	}
+
+	/* Convert to the # of pages available for stolen memory */
+	*pages = stolen_mem / 4096;
+
+	EMGD_DEBUG("Stolen memory: 0x%lx pages", *pages);
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param id
+ * @param value
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+int full_get_param_plb(igd_context_t *context,
+	unsigned long id,
+	unsigned long *value)
+{
+	int ret = 0;
+	unsigned char *mmio;
+	unsigned long control_reg;
+
+	EMGD_TRACE_ENTER;
+
+	EMGD_DEBUG("ID: 0x%lx", id);
+
+	/* Scratch registers used as below:
+	 *
+	 * 0x71410:
+	 * --------
+	 *   Bits 31-16 - EID Firmware identifier 0xE1DF
+	 *   Bits 15-00 - Tell what data is present.
+	 * Here are bits for what we are using know:
+	 *   Bit 0 - Panel id
+	 *   Bit 1 - List of ports for which displays are attached
+	 *   Bit 2 - Memory reservation
+	 * If any of the above bits is set that mean data is followed
+	 * in the next registers.
+	 *
+	 * 0x71414:
+	 * --------
+	 *   Bits 07-00 - Panel Id
+	 *   Bits 11-08 - Port list
+	 * Information for Port list: If any of the bit is set means,
+	 *   a display is attached to that port as follows:
+	 *    Bit 08 - CRT
+	 *    Bit 09 - DVOA/Internal LVDS
+	 *    Bit 10 - DVOB/RGBA
+	 *    Bit 11 - DVOC
+	 *
+	 * 0x71418:
+	 * --------
+	 *	 Bits 15-00 - Reserved Memory value in number of 4k size pages
+	 */
+	mmio = context->device_context.virt_mmadr;
+	control_reg = EMGD_READ32(EMGD_MMIO(mmio) + 0x71410);
+	*value = 0;
+
+	switch(id) {
+	case IGD_PARAM_PANEL_ID:
+		/*
+		 * Check for Embedded firmware
+		 */
+		if ((control_reg>>16) != 0xE1DF) {
+			EMGD_DEBUG("No Embedded vBIOS found");
+			EMGD_TRACE_EXIT;
+			return -IGD_ERROR_INVAL;
+		}
+
+		/*
+		 * The panel id bit must be set in the control register
+		 * to indicate valid panel (config) ID value.
+		 */
+		if (control_reg & 0x1) {
+			*value = EMGD_READ32(EMGD_MMIO(mmio) + 0x71414) & 0xFF;
+			if(!(*value)) {
+				/* we cannot allow for config id = 0 */
+				ret = -IGD_ERROR_INVAL;
+			}
+		} else {
+			EMGD_DEBUG("Panel ID read failed: Incorrect Operation");
+			ret = -IGD_ERROR_INVAL;
+		}
+		break;
+	case IGD_PARAM_MEM_RESERVATION:
+		/*
+		 * Check for Embedded firmware
+		 */
+		if ((control_reg>>16) != 0xE1DF) {
+			EMGD_DEBUG("No Embedded vBIOS found");
+			EMGD_TRACE_EXIT;
+			return -IGD_ERROR_INVAL;
+		}
+
+		/*
+		 * The mem reservation bit must be set in the control register
+		 * to indicate valid mem reservation value.
+		 */
+		if (control_reg & 0x4) {
+			*value = (EMGD_READ32(EMGD_MMIO(mmio) + 0x71418) & 0xFFFF);
+		} else {
+			EMGD_DEBUG("Mem Reservation read failed: Incorrect Operation");
+			ret = -IGD_ERROR_INVAL;
+		}
+		break;
+	default:
+		ret = -IGD_ERROR_INVAL;
+		break;
+	}
+
+	EMGD_TRACE_EXIT;
+	return ret;
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+void full_shutdown_plb(igd_context_t *context)
+{
+	platform_context_plb_t *platform_context =
+		(platform_context_plb_t *)context->platform_context;
+
+	EMGD_TRACE_ENTER;
+
+	/* unmap registers */
+	if(context->device_context.virt_mmadr) {
+		EMGD_DEBUG("Unmapping Gfx registers and GTT Table...");
+		OS_UNMAP_IO_FROM_MEM((void *) context->device_context.virt_mmadr,
+			PLB_MMIO_SIZE);
+		OS_UNMAP_IO_FROM_MEM((void *)context->device_context.virt_gttadr,
+			context->device_context.gatt_pages * 4);
+	} else {
+		printk(KERN_ERR "Unmapping MMIO space failed.\n");
+	}
+
+	if (platform_context) {
+		OS_PCI_FREE_DEVICE(platform_context->pcidev0);
+	}
+	EMGD_TRACE_EXIT;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/core/init/plb/micro_init_plb.c b/drivers/gpu/drm/emgd/emgd/core/init/plb/micro_init_plb.c
new file mode 100644
index 0000000..c91adb6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/core/init/plb/micro_init_plb.c
@@ -0,0 +1,631 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: micro_init_plb.c
+ * $Revision: 1.13 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.init
+
+#include <io.h>
+#include <pci.h>
+#include <memmap.h>
+
+#include <igd.h>
+#include <igd_errno.h>
+#include <igd_init.h>
+
+#include <context.h>
+#include <intelpci.h>
+#include <general.h>
+#include <utils.h>
+
+#include <igd_debug.h>
+#include <drmP.h>
+#include <memory.h>
+#include <asm/cacheflush.h>
+
+#include <plb/regs.h>
+#include <plb/context.h>
+
+#include "user_config.h"
+#include "../cmn/init_dispatch.h"
+
+/*!
+ * @addtogroup core_group
+ * @{
+ */
+
+#define PFX "EMGD: "
+
+#define SCR1    0x71410 /* scratch register set by vbios indicating status*/
+#define SCR2    0x71418 /* scratch register set by vbios indicating amount of stolen memory */
+#define FW_ID   0xE1DF0000 /* firmware identifier */
+#define ST_BIT  0x00000004 /* bit2- stolen memory bit */
+#define PSB_GMCH_CTRL       0x52
+#define PSB_GMCH_ENABLED    0x04
+#define PSB_PGETBL_CTL      0x00002020
+#define PSB_PGETBL_ENABLED  0x00000001
+#define PSB_GATT_RESOURCE   2
+#define PSB_GTT_RESOURCE    3
+#define PSB_BSM             0x5c
+#define PSB_PTE_VALID       0x0001
+
+
+#ifdef CONFIG_PLB
+
+extern unsigned char io_mapped;
+extern unsigned short io_base;
+extern emgd_drm_config_t config_drm;
+
+extern int full_config_plb(igd_context_t *context,
+	init_dispatch_t *dispatch);
+extern int get_revision_id_plb(igd_context_t *context, os_pci_dev_t vga_dev);
+extern int full_get_param_plb(igd_context_t *context, unsigned long id,
+	unsigned long *value);
+extern void full_shutdown_plb(igd_context_t *context);
+
+static int query_plb(igd_context_t *context,init_dispatch_t *dispatch,
+	os_pci_dev_t vga_dev, unsigned int *bus, unsigned int *slot,
+	unsigned int *func);
+static int config_plb(igd_context_t *context,
+	init_dispatch_t *dispatch);
+static int set_param_plb(igd_context_t *context, unsigned long id,
+	unsigned long value);
+static int get_param_plb(igd_context_t *context, unsigned long id,
+	unsigned long *value);
+static void shutdown_plb(igd_context_t *context);
+
+static void gtt_shutdown_plb(igd_context_t *context);
+static void gtt_init_plb(igd_context_t *context);
+
+
+static platform_context_plb_t platform_context_plb;
+
+/* Graphics frequency list. This is valid for pouslbo only. This value is obtained
+ * From the Cspec - SCH Message Network-Port 5*/
+static unsigned short plb_gfx_freq_list[] =
+{
+	100, 133, 150, 178, 200, 266, 0, 0
+};
+
+init_dispatch_t init_dispatch_plb = {
+	"Intel SCH US15 Chipset",
+	"US15",
+	"lvds",
+	query_plb,
+	config_plb,
+	set_param_plb,
+	get_param_plb,
+	shutdown_plb,
+	NULL
+};
+
+
+
+/*
+ * GTT shutdown.
+ *
+ * Unmap the GTT mapping that was done during init time.
+ */
+static void gtt_shutdown_plb(igd_context_t *context)
+{
+	if (context->device_context.virt_gttadr) {
+		iounmap(context->device_context.virt_gttadr);
+
+		context->device_context.virt_gttadr = NULL;
+	}
+}
+
+
+/*
+ * Initialize the GTT.
+ *   - Find the size of stolen memory
+ *   - Add stolen memory to the GTT
+ *   - Map the GTT and video memory
+ */
+
+static void gtt_init_plb(igd_context_t *context)
+{
+	struct drm_device *dev;
+	unsigned char *mmio = context->device_context.virt_mmadr;
+	unsigned long dvmt_mode = 0;
+	unsigned long gtt_pages = 0;
+	unsigned long stolen_mem_size = 0;
+	unsigned long scratch;
+	unsigned long base;
+	unsigned long pte;
+	unsigned short gmch_ctl;
+	unsigned long pge_ctl;
+	unsigned long gtt_phys_start;
+	unsigned long gatt_start;
+	unsigned long gatt_pages;
+	unsigned long gtt_start;
+	unsigned long gtt_order;
+	unsigned long stolen_mem_base;
+	unsigned long *gtt_table;
+	int gtt_enabled = FALSE;
+	struct page *gtt_table_page;
+	int i;
+
+	dev = (struct drm_device *)context->drm_dev;
+
+	/* Enable the GMCH */
+	OS_PCI_READ_CONFIG_16((os_pci_dev_t)dev->pdev, PSB_GMCH_CTRL,
+			&gmch_ctl);
+	OS_PCI_WRITE_CONFIG_16((os_pci_dev_t)dev->pdev, PSB_GMCH_CTRL,
+			(gmch_ctl | PSB_GMCH_ENABLED));
+	context->device_context.gmch_ctl = gmch_ctl;
+
+	/* Get the page table control register */
+	pge_ctl = readl(mmio + PSB_PGETBL_CTL);
+	gtt_phys_start = pge_ctl & PAGE_MASK;
+
+	gtt_enabled = pge_ctl & PSB_PGETBL_ENABLED;
+
+	/* Create a scratch page to initialize empty GTT entries */
+	context->device_context.scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO);
+
+	/*
+	* Is pci_resource_start(dev->pdev, PSB_GATT_RESOURCE); the same
+	* as pci_read_config_dword(dev->pdev, 0x1C, &value)?
+	*
+	* PSB_GATT_RESOURCE length is the amount of memory addressable
+	* by the GTT table.
+	*/
+	gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
+	gatt_pages = (pci_resource_len(dev->pdev, PSB_GATT_RESOURCE) >> PAGE_SHIFT);
+	context->device_context.gatt_pages = gatt_pages;
+
+	/*
+	 * The GTT wasn't set up by the vBios
+	 */
+	if (!gtt_enabled) {
+		context->device_context.stolen_pages = 0;
+
+		gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT;
+		gtt_order = get_order(gtt_pages << PAGE_SHIFT);
+		gtt_table = (unsigned long *)__get_free_pages(GFP_KERNEL, gtt_order);
+		/* Make sure allocation was successful */
+		if (NULL == gtt_table) {
+			EMGD_ERROR("Failed to allocate kernel pages for GTT");
+			return;
+		}
+		context->device_context.virt_gttadr = gtt_table;
+
+		for (i=0; i < (1 << gtt_order); i++) {
+			gtt_table_page = virt_to_page(gtt_table + (PAGE_SIZE * i));
+			EMGD_DEBUG("Setting reserved bit on %p", gtt_table_page);
+			set_bit(PG_reserved, &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/drivers/gpu/drm/emgd/emgd/core/init/tnc/init_tnc.c b/drivers/gpu/drm/emgd/emgd/core/init/tnc/init_tnc.c
new file mode 100644
index 0000000..c07d82d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/core/init/tnc/init_tnc.c
@@ -0,0 +1,621 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: init_tnc.c
+ * $Revision: 1.24 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.init
+
+#include <io.h>
+#include <pci.h>
+#include <memmap.h>
+#include <gart.h>
+
+#include <memory.h>
+#include <igd.h>
+#include <igd_errno.h>
+#include <igd_init.h>
+#include <igd_gart.h>
+
+#include <context.h>
+#include <intelpci.h>
+#include <general.h>
+
+#include <tnc/regs.h>
+#include <tnc/context.h>
+#include <tnc/igd_tnc_wa.h>
+
+#include "../cmn/init_dispatch.h"
+#include "/usr/include/linux/pci_regs.h"
+
+/*!
+ * @addtogroup core_group
+ * @{
+ */
+
+static int bus_master_enable_tnc(platform_context_tnc_t *platform_context);
+static int full_config_vga_tnc(igd_context_t *context,
+	init_dispatch_t *dispatch);
+static int get_stolen_mem_tnc(igd_context_t *context, unsigned long *pages);
+
+int full_get_param_tnc(igd_context_t *context,
+	unsigned long id,
+	unsigned long *value);
+
+
+/*!
+ *
+ * @param context
+ * @param dispatch
+ *
+ * @return 1 on failure
+ * @return 0 on success
+ */
+int full_config_tnc(igd_context_t *context,
+	init_dispatch_t *dispatch)
+{
+	unsigned long reserved_mem;
+	platform_context_tnc_t *platform_context;
+	int ret;
+
+	EMGD_TRACE_ENTER;
+
+	platform_context = (platform_context_tnc_t *)context->platform_context;
+
+	_sgx_base = 0x80000;
+	_msvdx_base = 0x90000;
+	_topaz_base = 0xA0000;
+
+	/*
+	 * Enable bus mastering for platforms whose BIOS did not perform this
+	 * task for us.
+	 */
+	ret = bus_master_enable_tnc(platform_context);
+	if(ret) {
+		EMGD_ERROR("Error: Enabling bus master");
+	}
+
+	/* Config VGA */
+	ret = full_config_vga_tnc(context, dispatch);
+	if(ret) {
+		EMGD_ERROR_EXIT("Config VGA Failed");
+		return ret;
+	}
+
+	get_stolen_mem_tnc(context, &context->device_context.reserved_mem);
+
+	/* Get mem reservation param if it exists */
+	if(!full_get_param_tnc(context, IGD_PARAM_MEM_RESERVATION,
+			&reserved_mem)) {
+		context->device_context.reserved_mem = reserved_mem;
+	}
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ *
+ * @param platform_context
+ *
+ * @return -1 on failure
+ * @return 0 on success
+ */
+/*
+ */
+static int bus_master_enable_tnc(platform_context_tnc_t *platform_context){
+	int ret;
+	unsigned char tmp, tmp_sdvo;
+
+	EMGD_TRACE_ENTER;
+
+	ret = OS_PCI_READ_CONFIG_8(platform_context->pcidev0, PCI_COMMAND_MASTER, &tmp);
+	if(ret) {
+		EMGD_ERROR_EXIT("PCI read of bus master");
+		return -1;
+	}
+
+	/*
+	 * Get Bit 2, 1, and 0 and see if it is == 1
+	 * all 3 bits has to be enabled. This is to enable register read/write
+	 * in the case of a PCI card being added
+	 */
+	if((tmp & 0x7) != 0x7 ) {
+
+		tmp |= 0x7;
+		ret = OS_PCI_WRITE_CONFIG_8(platform_context->pcidev0,PCI_COMMAND_MASTER, tmp);
+		if(ret) {
+			EMGD_ERROR_EXIT("PCI write of bus master");
+			return -1;
+		}
+	}
+
+
+	if (platform_context->pcidev1) {
+		ret = OS_PCI_READ_CONFIG_8(platform_context->pcidev1,PCI_COMMAND_MASTER, &tmp_sdvo);
+		if(ret) {
+			EMGD_ERROR_EXIT("PCI read of bus master");
+			return -1;
+		}
+
+		if((tmp_sdvo & 0x7) != 0x7 ) {
+			tmp_sdvo |= 0x7;
+			ret = OS_PCI_WRITE_CONFIG_8(platform_context->pcidev1,
+				PCI_COMMAND_MASTER,tmp_sdvo);
+			if(ret) {
+				EMGD_ERROR_EXIT("PCI write of bus master");
+				return -1;
+			}
+		}
+	}
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param dispatch
+ *
+ * @return -IGD_ERROR_NODEV on failure
+ * @return 0 on success
+ */
+static int full_config_vga_tnc(igd_context_t *context,
+	init_dispatch_t *dispatch)
+{
+	platform_context_tnc_t *platform_context =
+		(platform_context_tnc_t *)context->platform_context;
+
+	EMGD_TRACE_ENTER;
+
+	/*
+	 * Map the Device 2 MMIO register. These registers are similar to LNC
+	 * and is located in the Atom E6xx Hard Macro
+	 */
+	if(OS_PCI_READ_CONFIG_32(platform_context->pcidev0,
+			TNC_PCI_MMADR, (void*)&context->device_context.mmadr)) {
+		EMGD_ERROR_EXIT("Reading MMADR");
+		return -IGD_ERROR_NODEV;
+	}
+
+	context->device_context.mmadr &= 0xfffffff9;
+	context->device_context.virt_mmadr =
+		OS_MAP_IO_TO_MEM_NOCACHE(context->device_context.mmadr, TNC_D2_MMIO_SIZE);
+
+	if (!context->device_context.virt_mmadr) {
+		EMGD_ERROR_EXIT("Failed to map MMADR");
+		return -IGD_ERROR_NODEV;
+	}
+
+	EMGD_DEBUG("mmadr mapped %dKB @ (phys):0x%lx  (virt):%p",
+		TNC_D2_MMIO_SIZE/1024,
+		context->device_context.mmadr,
+		context->device_context.virt_mmadr);
+
+
+	/*
+	 * Map the device 3 MMIO registers. These are Atom E6xx specific registers
+	 * located in the Atom E6xx Overlay. On LNC, these registers are part of
+	 * the IOH (Langwell)
+	 */
+	if(OS_PCI_READ_CONFIG_32(platform_context->pcidev1,
+			TNC_PCI_MMADR, (void*)&context->device_context.mmadr_sdvo)) {
+		EMGD_ERROR_EXIT("Reading MMADR");
+		return -IGD_ERROR_NODEV;
+	}
+
+	context->device_context.mmadr_sdvo &= 0xfffffff9;
+	context->device_context.virt_mmadr_sdvo =
+		OS_MAP_IO_TO_MEM_NOCACHE(context->device_context.mmadr_sdvo,
+		TNC_D3_MMIO_SIZE);
+
+	if (!context->device_context.virt_mmadr_sdvo) {
+		EMGD_ERROR_EXIT("Failed to map MMADR");
+		return -IGD_ERROR_NODEV;
+	}
+
+	EMGD_DEBUG("sdvo mmadr mapped %dKB @ (phys):0x%lx  (virt):%p",
+		TNC_D3_MMIO_SIZE/1024,
+		context->device_context.mmadr_sdvo,
+		context->device_context.virt_mmadr_sdvo);
+
+	/* Map the STMicro SDVO registers. */
+	if(platform_context->stbridgedev) {
+		if(OS_PCI_READ_CONFIG_32(platform_context->stbridgedev,
+					TNC_PCI_MMADR, (void*)&context->device_context.mmadr_sdvo_st)) {
+			EMGD_ERROR_EXIT("Reading MMADR");
+			return -IGD_ERROR_NODEV;
+		}
+
+		context->device_context.mmadr_sdvo_st &= 0xfffffff9;
+		context->device_context.virt_mmadr_sdvo_st =
+			OS_MAP_IO_TO_MEM_NOCACHE(context->device_context.mmadr_sdvo_st,
+					TNC_ST_SDVO_MMIO_SIZE);
+
+		if (!context->device_context.virt_mmadr_sdvo_st) {
+			EMGD_ERROR_EXIT("Failed to map MMADR");
+			return -IGD_ERROR_NODEV;
+		}
+
+		EMGD_DEBUG("STMicro sdvo mmadr mapped %dKB @ (phys):0x%lx  (virt):%p",
+				TNC_ST_SDVO_MMIO_SIZE/1024,
+				context->device_context.mmadr_sdvo_st,
+				context->device_context.virt_mmadr_sdvo_st);
+
+		/* Map the STMicro GPIO registers. */
+		if(OS_PCI_READ_CONFIG_32(platform_context->stgpiodev,
+					TNC_PCI_MMADR, (void*)&context->device_context.mmadr_sdvo_st_gpio)) {
+			EMGD_ERROR_EXIT("Reading MMADR");
+			return -IGD_ERROR_NODEV;
+		}
+
+		context->device_context.mmadr_sdvo_st_gpio &= 0xfffffff9;
+		context->device_context.virt_mmadr_sdvo_st_gpio =
+			OS_MAP_IO_TO_MEM_NOCACHE(context->device_context.mmadr_sdvo_st_gpio,
+					TNC_ST_SDVO_MMIO_SIZE);
+
+		if (!context->device_context.virt_mmadr_sdvo_st_gpio) {
+			EMGD_ERROR_EXIT("Failed to map MMADR");
+			return -IGD_ERROR_NODEV;
+		}
+
+		EMGD_DEBUG("STMicro sdvo gpio mmadr mapped %dKB @ (phys):0x%lx  (virt):%p",
+				TNC_ST_SDVO_MMIO_SIZE/1024,
+				context->device_context.mmadr_sdvo_st_gpio,
+				context->device_context.virt_mmadr_sdvo_st_gpio);
+	}
+
+	/* Map the GPIO BAR. Provides the 64 bytes of I/O space for GPIO
+	 * BAR is defined by bits 15:6 */
+
+	if(OS_PCI_READ_CONFIG_16(platform_context->lpc_dev,
+			TNC_PCI_GBA, (void*)&context->device_context.gpio_bar)) {
+
+	}
+	context->device_context.gpio_bar |= (1L<<31);
+	/* Enable the decode of IO Range ppointed to by the BA */
+	if(OS_PCI_WRITE_CONFIG_32(platform_context->lpc_dev,
+		TNC_PCI_GBA, context->device_context.gpio_bar)) {
+		EMGD_ERROR_EXIT("Writing LPC GPIO BAR Enable");
+	}
+
+	/* read the GPIO BAR (OFFSET 44:47) */
+	if(OS_PCI_READ_CONFIG_16(platform_context->lpc_dev,
+			TNC_PCI_GBA, (void*)&context->device_context.gpio_bar)) {
+		EMGD_ERROR_EXIT("Reading LPC GPIO BAR");
+		/* We cannot read the GPIO BAR. It is a problem but we can go on with init
+		 * return with NO ERROR*/
+		return 0;
+	}
+
+	context->device_context.gpio_bar &= 0xffc0;
+
+	context->device_context.virt_gpio_bar =
+		OS_MAP_IO_TO_MEM_NOCACHE(
+		context->device_context.gpio_bar, 64);
+
+	if (!context->device_context.virt_gpio_bar) {
+		EMGD_ERROR_EXIT("Failed to map LPC GPIO BAR");
+		return -IGD_ERROR_NODEV;
+	}
+
+	EMGD_DEBUG("GPIO mapped %dKB @ (phys):0x%lx  (virt):%p",
+		64,
+		context->device_context.gpio_bar,
+		context->device_context.virt_gpio_bar);
+
+	/* PCI Interrupt Line */
+	if(OS_PCI_READ_CONFIG_8(platform_context->pcidev0,
+			PCI_INTERRUPT_LINE, (void*)&platform_context->irq)) {
+		platform_context->irq = 0;
+	}
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ * Get the # of pages used for video memory. This does not use information from
+ * the scratch register, since this is done later if it exists.
+ *
+ * @param context
+ * @param pages
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+static int get_stolen_mem_tnc(igd_context_t *context, unsigned long *pages)
+{
+	platform_context_tnc_t *platform_context;
+	os_pci_dev_t           vga_dev;
+	unsigned short         gmch_ctl;
+	unsigned long          stolen_mem; /* in bytes */
+	int ret;
+
+	EMGD_TRACE_ENTER;
+
+	platform_context = (platform_context_tnc_t *)context->platform_context;
+	vga_dev = platform_context->pcidev0;
+
+	ret = OS_PCI_READ_CONFIG_16(vga_dev, TNC_PCI_GC, &gmch_ctl);
+	if (ret) {
+		EMGD_ERROR_EXIT("Unable to read TNC_PCI_GC");
+		return -IGD_ERROR_INVAL;
+	}
+
+	switch (gmch_ctl & 0x70) {
+	case 0x00:
+		stolen_mem = 0;
+		break;
+	case 0x10:
+		/* 1M */
+		stolen_mem = 1*1024*1024;
+		break;
+	case 0x20:
+		/* 4M */
+		stolen_mem = 4*1024*1024;
+		break;
+	case 0x30:
+		/* 8M */
+		stolen_mem = 8*1024*1024;
+		break;
+	case 0x40:
+		/* 16M */
+		stolen_mem = 16*1024*1024;
+		break;
+	case 0x50:
+		/* 32M */
+		stolen_mem = 32*1024*1024;
+		break;
+	case 0x60:
+		/* 48M */
+		stolen_mem = 48*1024*1024;
+	case 0x70:
+		/* 64M */
+		stolen_mem = 64*1024*1024;
+		break;
+	default:
+		EMGD_ERROR_EXIT("Unknown Stolen Memory Size");
+		return -IGD_ERROR_INVAL;
+	}
+
+	if (stolen_mem) {
+		/*
+		 * Subtract off the size of the GTT which is
+		 * (number of entries in DWORDS) * 4 to get it into bytes
+		 */
+		stolen_mem -= context->device_context.gatt_pages*4;
+		/* Subtract off 1 page for the scratch page */
+		stolen_mem -= 4*1024;
+	}
+
+	/* Convert to the # of pages available for stolen memory */
+	*pages = stolen_mem / 4096;
+
+	EMGD_DEBUG("Stolen memory: 0x%lx pages", *pages);
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param id
+ * @param value
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+int full_get_param_tnc(igd_context_t *context,
+	unsigned long id,
+	unsigned long *value)
+{
+	int ret = 0;
+	unsigned char *mmio;
+	unsigned long control_reg;
+
+	EMGD_TRACE_ENTER;
+
+	EMGD_DEBUG("ID: 0x%lx", id);
+
+	/* Scratch registers used as below:
+	 *
+	 * 0x71410:
+	 * --------
+	 *   Bits 31-16 - EID Firmware identifier 0xE1DF
+	 *   Bits 15-00 - Tell what data is present.
+	 * Here are bits for what we are using know:
+	 *   Bit 0 - Panel id
+	 *   Bit 1 - List of ports for which displays are attached
+	 *   Bit 2 - Memory reservation
+	 * If any of the above bits is set that mean data is followed
+	 * in the next registers.
+	 *
+	 * 0x71414:
+	 * --------
+	 *   Bits 07-00 - Panel Id
+	 *   Bits 11-08 - Port list
+	 * Information for Port list: If any of the bit is set means,
+	 *   a display is attached to that port as follows:
+	 *    Bit 08 - CRT
+	 *    Bit 09 - DVOA/Internal LVDS
+	 *    Bit 10 - DVOB/RGBA
+	 *    Bit 11 - DVOC
+	 *
+	 * 0x71418:
+	 * --------
+	 *	 Bits 15-00 - Reserved Memory value in number of 4k size pages
+	 */
+	mmio = context->device_context.virt_mmadr;
+	control_reg = EMGD_READ32(EMGD_MMIO(mmio) + 0x71410);
+	*value = 0;
+
+	switch(id) {
+	case IGD_PARAM_PANEL_ID:
+		/*
+		 * Check for Embedded firmware
+		 */
+		if ((control_reg>>16) != 0xE1DF) {
+			EMGD_DEBUG("No Embedded vBIOS found");
+			EMGD_TRACE_EXIT;
+			return -IGD_ERROR_INVAL;
+		}
+
+		/*
+		 * The panel id bit must be set in the control register
+		 * to indicate valid panel (config) ID value.
+		 */
+		if (control_reg & 0x1) {
+			*value = EMGD_READ32(EMGD_MMIO(mmio) + 0x71414) & 0xFF;
+			if(!(*value)) {
+				/* we cannot allow for config id = 0 */
+				ret = -IGD_ERROR_INVAL;
+			}
+		} else {
+			EMGD_DEBUG("Panel ID read failed: Incorrect Operation");
+			ret = -IGD_ERROR_INVAL;
+		}
+		break;
+	case IGD_PARAM_MEM_RESERVATION:
+		/*
+		 * Check for Embedded firmware
+		 */
+		if ((control_reg>>16) != 0xE1DF) {
+			EMGD_DEBUG("No Embedded vBIOS found");
+			EMGD_TRACE_EXIT;
+			return -IGD_ERROR_INVAL;
+		}
+
+		/*
+		 * The mem reservation bit must be set in the control register
+		 * to indicate valid mem reservation value.
+		 */
+		if (control_reg & 0x4) {
+			*value = (EMGD_READ32(EMGD_MMIO(mmio) + 0x71418) & 0xFFFF);
+		} else {
+			EMGD_DEBUG("Mem Reservation read failed: Incorrect Operation");
+			ret = -IGD_ERROR_INVAL;
+		}
+		break;
+	default:
+		ret = -IGD_ERROR_INVAL;
+		break;
+	}
+
+	EMGD_TRACE_EXIT;
+	return ret;
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+void full_shutdown_tnc(igd_context_t *context)
+{
+	platform_context_tnc_t *platform_context =
+		(platform_context_tnc_t *)context->platform_context;
+
+	EMGD_TRACE_ENTER;
+
+	/* unmap registers */
+	if(context->device_context.virt_mmadr) {
+		EMGD_DEBUG("Unmapping Gfx registers and GTT Table...");
+		OS_UNMAP_IO_FROM_MEM((void *)context->device_context.virt_mmadr,
+			TNC_D2_MMIO_SIZE);
+		OS_UNMAP_IO_FROM_MEM((void *)context->device_context.virt_mmadr_sdvo,
+			TNC_D3_MMIO_SIZE);
+		OS_UNMAP_IO_FROM_MEM((void *)context->device_context.virt_mmadr_sdvo_st,
+			TNC_ST_SDVO_MMIO_SIZE);
+		OS_UNMAP_IO_FROM_MEM((void *)context->device_context.virt_mmadr_sdvo_st_gpio,
+			TNC_ST_SDVO_MMIO_SIZE);
+		OS_UNMAP_IO_FROM_MEM((void *)context->device_context.virt_gpio_bar, 64);
+
+		OS_UNMAP_IO_FROM_MEM((void *)context->device_context.virt_gttadr,
+			context->device_context.gatt_pages * 4);
+	} else {
+		printk(KERN_ERR "Unmapping MMIO space failed.\n");
+	}
+
+	if (platform_context) {
+		OS_PCI_FREE_DEVICE(platform_context->pcidev0);
+		OS_PCI_FREE_DEVICE(platform_context->pcidev1);
+		OS_PCI_FREE_DEVICE(platform_context->bridgedev);
+		if (platform_context->lpc_dev) {
+			OS_PCI_FREE_DEVICE(platform_context->lpc_dev);
+		}
+	}
+	EMGD_TRACE_EXIT;
+}
+
+
+ int query_2d_caps_hwhint_tnc(
+  	         igd_context_t *context,
+  	         unsigned long caps_val,
+  	         unsigned long *status)
+{
+	platform_context_tnc_t *platform_context;
+	  	 
+	EMGD_TRACE_ENTER;
+
+ 
+	platform_context = (platform_context_tnc_t *)context->platform_context;
+ 	 	 
+	/*
+	* Only 2D BLT capability query is currently implemented.
+	* This is required by TNC B0 flickering workaround.
+	* Query for other 2D capability can be implemented
+	* in the future if neeeded.
+	*/
+	switch (caps_val) {
+		case IGD_2D_CAPS_BLT:
+			if((context->device_context.did == PCI_DEVICE_ID_VGA_TNC) &&
+				(context->device_context.rid == TNC_B0_RID) &&
+				(platform_context->tnc_dev3_rid == TNC_B0_DEV3_RID)) {
+					*status = IGD_2D_HW_DISABLE;                    
+					/* disable 2d blt hardware acceleration for TNC B0 */
+			} else {
+					*status = IGD_2D_HW_ENABLE;                             
+					/* enable 2d blt hardware acceleration */  	
+			}
+		break;
+  	 
+		default:
+			*status = IGD_2D_CAPS_UNKNOWN;                          
+			/* Unknown 2d capability to query */
+			EMGD_ERROR("2D caps to query is unknown!");
+		break;
+	}
+  	 
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/core/init/tnc/micro_init_tnc.c b/drivers/gpu/drm/emgd/emgd/core/init/tnc/micro_init_tnc.c
new file mode 100644
index 0000000..dd2d1d0
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/core/init/tnc/micro_init_tnc.c
@@ -0,0 +1,998 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: micro_init_tnc.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:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#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];
+#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);
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param id
+ * @param value
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+static int get_param_tnc(igd_context_t *context, unsigned long id,
+	unsigned long *value)
+{
+#define FB_SKU_MASK  (BIT12|BIT13|BIT14)
+#define FB_SKU_SHIFT 12
+#define FB_GFX_CLOCK_DIVIDE_MASK  (BIT20|BIT21|BIT22)
+#define FB_GFX_CLOCK_DIVIDE_SHIFT 20
+
+	int ret = 0;
+	unsigned long control_reg;
+	unsigned short sku;
+	unsigned short ratio;
+
+	EMGD_TRACE_ENTER;
+
+	EMGD_DEBUG("ID: 0x%lx", id);
+
+	/* Scratch registers used as below:
+	 *
+	 * 0x71410:
+	 * --------
+	 *   Bits 31-16 - EID Firmware identifier 0xE1DF
+	 *   Bits 15-00 - Tell what data is present.
+	 * Here are bits for what we are using know:
+	 *   Bit 0 - Panel id
+	 *   Bit 1 - List of ports for which displays are attached
+	 *   Bit 2 - Memory reservation
+	 * If any of the above bits is set that mean data is followed
+	 * in the next registers.
+	 *
+	 * 0x71414:
+	 * --------
+	 *   Bits 07-00 - Panel Id
+	 *   Bits 11-08 - Port list
+	 * Information for Port list: If any of the bit is set means,
+	 *   a display is attached to that port as follows:
+	 *    Bit 08 - CRT
+	 *    Bit 09 - DVOA/Internal LVDS
+	 *    Bit 10 - DVOB/RGBA
+	 *    Bit 11 - DVOC
+	 *
+	 * 0x71418:
+	 * --------
+	 * Bits 15-00 - Reserved Memory value in number of 4k size pages
+	 */
+	*value = 0;
+
+	switch(id) {
+	case IGD_PARAM_PORT_LIST:
+
+		control_reg = EMGD_READ32(EMGD_MMIO(context->device_context.virt_mmadr) +
+			0x71410);
+
+		/*
+		 * Verify that the Embedded Firware is present.
+		 */
+		if ((control_reg>>16) != 0xE1DF) {
+			EMGD_DEBUG("Exit No Embedded vBIOS found");
+			EMGD_TRACE_EXIT;
+			return -IGD_ERROR_INVAL;
+		}
+
+		/*
+		 * If the port list bit is set in control register,
+		 * read the port list
+		 */
+		if (control_reg & 0x2) {
+			unsigned char temp;
+			int i = 0;
+
+			temp = (unsigned char)((EMGD_READ32(EMGD_MMIO(context->device_context.virt_mmadr) + 0x71414)>>8) & 0xFF);
+			EMGD_DEBUG("Connected Port Bits: 0x%x", temp);
+
+			/*
+			 * The meanings of bits in temp were dictated by VBIOS
+			 * and should not change due to backward compatibility
+			 * with Legacy VBIOS
+			 */
+			if (temp & 0x02) {
+				/* Internal LVDS port */
+				value[i++] = 4;
+			}
+			if (temp & 0x04) {
+				/* DVOB Port */
+				value[i++] = 2;
+			}
+		} else {
+			EMGD_DEBUG("Port List read failed: Incorrect Operation");
+			ret = -IGD_ERROR_INVAL;
+		}
+		break;
+	case IGD_PARAM_GFX_FREQ:
+
+		/* Read the fuse value */
+		if(query_sch_message(READ_FUS_EFF3, &control_reg)){
+			EMGD_ERROR("Cannot read GFX clock");
+		}
+		EMGD_DEBUG("SKU [reg 0x%x] value = 0x%lx", READ_FUS_EFF3, control_reg);
+
+		/*
+		 * Sku and Ratio bits determine the gfx clock speed
+		 * sku - 0:sku_100 1:sku_100L 2:sku_83
+		 * ratio - 0-1:1 1-4:3 2-8:5 3-2:1 4-16:7(rsvd) 5-8:3 6-16:5 7:4:1(rsvd)
+		 */
+		sku = (unsigned short)((control_reg & FB_SKU_MASK) >> FB_SKU_SHIFT) & 0x3;
+		ratio = (unsigned short)((control_reg & FB_GFX_CLOCK_DIVIDE_MASK) >> FB_GFX_CLOCK_DIVIDE_SHIFT) & 0x7;
+
+		EMGD_DEBUG("sku = 0x%x Ratio = 0x%x", sku, ratio);
+
+		if(sku < SKU_NO && ratio < RATIO_NO){
+			/* get the graphics clock speed from the sku-ratio array */
+			value[0] = tnc_gfx_freq_list[ratio][sku];
+			value[1] = tnc_core_freq_list[sku];
+		} else {
+			EMGD_ERROR("tnc_gfx_freq_list ARRAY OUT OF RANGE");
+			/* set to the lowest default value */
+			value[0] = 333;
+			value[1] = 166;
+		}
+
+		EMGD_DEBUG("TNC GFX core frequency = %lu MHz", value[0]);
+		EMGD_DEBUG("TNC Core clock frequency = %lu MHz", value[1]);
+
+		break;
+
+	default:
+		/* If the param is not found here then it may only be in the
+		 * full version.
+		 */
+		OPT_MICRO_CALL_RET(ret, full_get_param_tnc(context, id, value));
+		break;
+	}
+
+	EMGD_TRACE_EXIT;
+	return ret;
+}
+
+/*!
+ *
+ * @param context
+ * @param id
+ * @param value
+ *
+ * @return -IGD_ERROR_INVAL
+ */
+static int set_param_tnc(igd_context_t *context, unsigned long id,
+	unsigned long value)
+{
+	return 0;
+}
+
+/*!
+ * Functions reads all the fuse values and dumps out the value
+ * @return -IGD_ERROR_INVAL
+ */
+#ifndef CONFIG_MICRO
+static int dump_fuse_values(void)
+{
+	unsigned long value = 0;
+
+	if(query_sch_message(READ_FUS_EFF0, &value)){
+		EMGD_ERROR_EXIT("Reading Fuse Value Failed");
+	}
+	EMGD_DEBUG("READ_FUS_EFF0 [%lx]", value);
+
+	if(query_sch_message(READ_FUS_EFF1, &value)){
+		EMGD_ERROR_EXIT("Reading Fuse Value Failed");
+	}
+	EMGD_DEBUG("READ_FUS_EFF1 [%lx]", value);
+
+	if(query_sch_message(READ_FUS_EFF2, &value)){
+		EMGD_ERROR_EXIT("Reading Fuse Value Failed");
+	}
+	EMGD_DEBUG("READ_FUS_EFF2 [%lx]", value);
+
+	if(query_sch_message(READ_FUS_EFF3, &value)){
+		EMGD_ERROR_EXIT("Reading Fuse Value Failed");
+	}
+	EMGD_DEBUG("READ_FUS_EFF3 [%lx]", value);
+
+	if(query_sch_message(READ_FUS_EFF4, &value)){
+		EMGD_ERROR_EXIT("Reading Fuse Value Failed");
+	}
+	EMGD_DEBUG("READ_FUS_EFF4 [%lx]", value);
+
+	if(query_sch_message(READ_FUS_EFF5, &value)){
+		EMGD_ERROR_EXIT("Reading Fuse Value Failed");
+	}
+	EMGD_DEBUG("READ_FUS_EFF5 [%lx]", value);
+
+	return 0;
+}
+#endif
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+static void shutdown_tnc(igd_context_t *context)
+{
+	gtt_shutdown_tnc(context);
+
+	OPT_MICRO_VOID_CALL(full_shutdown_tnc(context));
+}
+
+
+/*!
+ *
+ * @param context
+ * @param dispatch
+ * @param vga_dev
+ *
+ * @return -IGD_ERROR_NODEV on failure
+ * @return 0 on success
+ */
+int get_revision_id_tnc(igd_context_t *context,
+	os_pci_dev_t vga_dev,
+	os_pci_dev_t sdvo_dev)
+{
+	platform_context_tnc_t *platform_context;
+
+	EMGD_TRACE_ENTER;
+  	 
+	platform_context = (platform_context_tnc_t *)context->platform_context;
+
+	/* Read RID */
+	if(OS_PCI_READ_CONFIG_8(vga_dev, PCI_RID,
+		(unsigned char *)&context->device_context.rid)) {
+		EMGD_ERROR_EXIT("Error occured reading RID");
+		return -IGD_ERROR_NODEV;
+	}
+  	 
+	if(OS_PCI_READ_CONFIG_8(sdvo_dev, PCI_RID,
+		&platform_context->tnc_dev3_rid)) {
+		EMGD_ERROR_EXIT("Error occured reading TNC SDVO RID");
+		return -IGD_ERROR_NODEV;
+	}
+  	 
+	EMGD_DEBUG(" rid = 0x%lx", context->device_context.rid);
+	
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp.c b/drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp.c
new file mode 100755
index 0000000..d4abefb
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp.c
@@ -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/drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp_dispatch.h b/drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp_dispatch.h
new file mode 100644
index 0000000..8431df4
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/dsp/cmn/dsp_dispatch.h
@@ -0,0 +1,64 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: dsp_dispatch.h
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _DSP_DISPATCH_H
+#define _DSP_DISPATCH_H
+
+#include <igd.h>
+#include <igd_init.h>
+#include <igd_mode.h>
+
+#include <mode.h>
+
+/*
+ * FIXME: This belong to PI, remove the defaults and let PI set
+ * them as it does for i2c.
+ */
+#define DDC_DEFAULT_SPEED  10  /* Default DDC bus speed in KHz */
+
+typedef struct _dsp_dispatch {
+	igd_plane_t **planes;
+	igd_display_pipe_t **pipes;
+	igd_display_port_t **ports;
+	igd_fb_caps_t *caps;
+	unsigned long *overlay_pfs;
+	unsigned long *render_pfs;
+	unsigned long *texture_pfs;
+	int (*dsp_init)(igd_context_t *context);
+	void (*dsp_control_plane_format)(igd_context_t *context,
+			int enable, int display_plane, 
+			igd_plane_t *plane_override);
+} dsp_dispatch_t;
+
+extern dsp_dispatch_t dsp_dispatch_plb;
+extern dsp_dispatch_t dsp_dispatch_tnc;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/display/dsp/plb/dsp_plb.c b/drivers/gpu/drm/emgd/emgd/display/dsp/plb/dsp_plb.c
new file mode 100644
index 0000000..9330537
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/dsp/plb/dsp_plb.c
@@ -0,0 +1,709 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: dsp_plb.c
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+#include <io.h>
+#include <memory.h>
+
+#include <igd.h>
+#include <igd_mode.h>
+#include <igd_pwr.h>
+
+#include <mode.h>
+#include <utils.h>
+
+#include <plb/regs.h>
+#include <plb/context.h>
+
+#include "../cmn/dsp_dispatch.h"
+
+#ifdef CONFIG_PLB
+
+extern igd_framebuffer_info_t fb_info_cmn[];
+
+/*
+ * NOTE: Some of these format lists are shared with GMM. For this reason
+ * they cannot be static.
+ */
+unsigned long fb_pixel_formats_plb[] = {
+	IGD_PF_ARGB32,
+	IGD_PF_xRGB32,
+	IGD_PF_ABGR32,
+	IGD_PF_ARGB32_2101010,
+	IGD_PF_RGB16_565,
+	IGD_PF_ARGB8_INDEXED,
+	0
+};
+
+unsigned long vga_pixel_formats_plb[] = {
+	IGD_PF_ARGB8_INDEXED,
+	0
+};
+
+#ifndef CONFIG_MICRO
+unsigned long sprite_pixel_formats_plb[] = {
+	IGD_PF_ARGB32,
+	IGD_PF_ABGR32,
+	IGD_PF_ARGB32_2101010,
+	IGD_PF_RGB16_565,
+	IGD_PF_ARGB8_INDEXED,
+	IGD_PF_YUV422_PACKED_YUY2,
+	IGD_PF_YUV422_PACKED_UYVY,
+	0
+};
+
+unsigned long render_pixel_formats_plb[] = {
+	IGD_PF_ARGB32,
+	IGD_PF_xRGB32,
+	IGD_PF_ARGB32_2101010,
+	IGD_PF_RGB16_565,
+	IGD_PF_xRGB16_555,
+	IGD_PF_ARGB16_1555,
+	IGD_PF_ARGB16_4444,
+	IGD_PF_YUV422_PACKED_YUY2,
+	IGD_PF_YUV422_PACKED_UYVY,
+	IGD_PF_R16F,
+	IGD_PF_GR32_1616F,
+	IGD_PF_R32F,
+	IGD_PF_ABGR64_16161616F,
+	IGD_PF_YUV420_PLANAR_NV12,
+	IGD_PF_YUV410_PLANAR_YVU9,
+	0
+};
+
+unsigned long texture_pixel_formats_plb[] = {
+	IGD_PF_ARGB32,
+	IGD_PF_xRGB32,
+	IGD_PF_ABGR32,
+	IGD_PF_xBGR32,
+	IGD_PF_RGB16_565,
+	IGD_PF_xRGB16_555,
+	IGD_PF_ARGB16_1555,
+	IGD_PF_ARGB16_4444,
+	IGD_PF_ARGB8_INDEXED,
+	IGD_PF_YUV422_PACKED_YUY2,
+	IGD_PF_YUV422_PACKED_UYVY,
+	IGD_PF_YUV420_PLANAR_I420,
+	IGD_PF_YUV420_PLANAR_IYUV,
+	IGD_PF_YUV420_PLANAR_YV12,
+	IGD_PF_YUV410_PLANAR_YVU9,
+	IGD_PF_YUV420_PLANAR_NV12,
+	IGD_PF_DVDU_88,
+	IGD_PF_LDVDU_655,
+	IGD_PF_xLDVDU_8888,
+	IGD_PF_DXT1,
+	IGD_PF_DXT2,
+	IGD_PF_DXT3,
+	IGD_PF_DXT4,
+	IGD_PF_DXT5,
+	IGD_PF_L8,
+	IGD_PF_A8,
+	IGD_PF_AL88,
+	IGD_PF_AI44,
+	IGD_PF_L16,
+	IGD_PF_ARGB32_2101010,
+	IGD_PF_AWVU32_2101010,
+	IGD_PF_QWVU32_8888,
+	IGD_PF_GR32_1616,
+	IGD_PF_VU32_1616,
+	IGD_PF_R16F,
+	IGD_PF_GR32_1616F,
+	IGD_PF_R32F,
+	IGD_PF_ABGR64_16161616F,
+	0
+};
+
+unsigned long depth_pixel_formats_plb[] = {
+	IGD_PF_Z16,
+	IGD_PF_Z24,
+	IGD_PF_S8Z24,
+	0
+};
+
+
+unsigned long cursor_pixel_formats_plb[] = {
+	IGD_PF_ARGB32,
+	IGD_PF_RGB_2,
+	IGD_PF_RGB_XOR_2,
+	IGD_PF_RGB_T_2,
+	0
+};
+
+unsigned long overlay_pixel_formats_plb[] = {
+	IGD_PF_YUV422_PACKED_YUY2,
+	IGD_PF_YUV422_PACKED_UYVY,
+	IGD_PF_YUV420_PLANAR_I420,
+	IGD_PF_YUV420_PLANAR_IYUV,
+	IGD_PF_YUV420_PLANAR_YV12,
+	IGD_PF_YUV420_PLANAR_NV12,
+	IGD_PF_YUV410_PLANAR_YVU9,
+	0
+};
+
+unsigned long video_pixel_formats_plb[] = {
+	IGD_PF_YUV420_PLANAR_NV12,
+	0
+};
+
+unsigned long blt_pixel_formats_plb[] = {
+	IGD_PF_ARGB32,
+	IGD_PF_xRGB32,
+	IGD_PF_ABGR32,
+	IGD_PF_xBGR32,
+	IGD_PF_RGB16_565,
+	IGD_PF_xRGB16_555,
+	IGD_PF_ARGB16_1555,
+	IGD_PF_ARGB16_4444,
+	IGD_PF_ARGB8_INDEXED,
+	IGD_PF_YUV422_PACKED_YUY2,
+	IGD_PF_YUV422_PACKED_UYVY,
+	IGD_PF_YUV420_PLANAR_I420,
+	IGD_PF_YUV420_PLANAR_IYUV,
+	IGD_PF_YUV420_PLANAR_YV12,
+	IGD_PF_YUV420_PLANAR_NV12,
+	IGD_PF_YUV410_PLANAR_YVU9,
+	IGD_PF_DVDU_88,
+	IGD_PF_LDVDU_655,
+	IGD_PF_xLDVDU_8888,
+	IGD_PF_DXT1,
+	IGD_PF_DXT2,
+	IGD_PF_DXT3,
+	IGD_PF_DXT4,
+	IGD_PF_DXT5,
+	IGD_PF_Z16,
+	IGD_PF_Z24,
+	IGD_PF_S8Z24,
+	IGD_PF_RGB_2,
+	IGD_PF_RGB_XOR_2,
+	IGD_PF_RGB_T_2,
+	IGD_PF_L8,
+	IGD_PF_A8,
+	IGD_PF_AL88,
+	IGD_PF_AI44,
+	IGD_PF_L16,
+	IGD_PF_ARGB32_2101010,
+	IGD_PF_AWVU32_2101010,
+	IGD_PF_QWVU32_8888,
+	IGD_PF_GR32_1616,
+	IGD_PF_VU32_1616,
+	IGD_PF_R16F,
+	IGD_PF_GR32_1616F,
+	IGD_PF_R32F,
+	IGD_PF_ABGR64_16161616F,
+	0
+};
+
+static igd_fb_caps_t caps_table_plb[] = {
+	{IGD_PF_ARGB32, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+	{IGD_PF_xRGB32, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+	{IGD_PF_ABGR32, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+	{IGD_PF_xBGR32, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+	{IGD_PF_ARGB32_2101010, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+	{IGD_PF_RGB16_565, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+	{IGD_PF_ARGB8_INDEXED, IGD_CAP_FULL_2D},
+	{0, 0}
+};
+
+#endif
+
+/*
+ * Plane Definitions for PLB family.
+ */
+static igd_plane_t planea_plb = {
+	DSPACNTR, IGD_PLANE_DISPLAY | IGD_PLANE_DIH, 0, 0,
+	fb_pixel_formats_plb, &fb_info_cmn[0], NULL
+};
+
+static igd_plane_t planeb_plb = {
+	DSPBCNTR, IGD_PLANE_DISPLAY | IGD_PLANE_SPRITE | IGD_PLANE_DIH, 0, 0,
+	fb_pixel_formats_plb, &fb_info_cmn[1], NULL
+};
+
+static igd_plane_t planec_plb = {
+	DSPCCNTR, IGD_PLANE_SPRITE, 0, 0,
+	OPT_MICRO_VALUE(sprite_pixel_formats_plb, NULL), NULL, NULL
+};
+
+static igd_plane_t plane_vga_plb = {
+	VGACNTRL, IGD_PLANE_VGA, 0, 0,
+	vga_pixel_formats_plb, NULL, NULL
+};
+
+static igd_plane_t plane_overlay_plb = {
+	OVADD, IGD_PLANE_OVERLAY, 0, 0,
+	OPT_MICRO_VALUE(overlay_pixel_formats_plb, NULL), NULL, NULL
+};
+
+static igd_plane_t plane_cursora_plb = {
+	CUR_A_CNTR, IGD_PLANE_CURSOR|IGD_CURSOR_USE_PIPEA|IGD_CURSOR_USE_PIPEB, 0,0,
+	OPT_MICRO_VALUE(cursor_pixel_formats_plb, NULL), NULL, NULL
+};
+
+static igd_plane_t plane_cursorb_plb = {
+	CUR_B_CNTR, IGD_PLANE_CURSOR|IGD_CURSOR_USE_PIPEA|IGD_CURSOR_USE_PIPEB, 0,0,
+	OPT_MICRO_VALUE(cursor_pixel_formats_plb, NULL), NULL, NULL
+};
+
+/*
+ * Plane lists for PLB family members.
+ */
+/* Two Main Plane, One Sprite, One VGA, One Overlay, Two Cursor */
+static igd_plane_t *plane_table_plb[] = {
+	&planeb_plb,
+	&planea_plb,
+	&planec_plb,
+	&plane_vga_plb,
+	&plane_overlay_plb,
+	&plane_cursora_plb,
+	&plane_cursorb_plb,
+	NULL
+};
+
+static igd_clock_t clock_a_plb = {
+	DPLLACNTR, FPA0, 16
+};
+
+static igd_clock_t clock_b_plb = {
+	DPLLBCNTR, FPB0, 16
+};
+
+/*
+ * Pipe definitions for PLB family.
+ */
+static igd_display_pipe_t pipea_plb = {
+	0, PIPEA_CONF, PIPEA_TIMINGS, DPALETTE_A, &clock_a_plb,
+	(IGD_PIPE_IS_PIPEA | IGD_PORT_SHARE_DIGITAL),
+	0, 0,{NULL, NULL, NULL}, 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/drivers/gpu/drm/emgd/emgd/display/dsp/tnc/dsp_tnc.c b/drivers/gpu/drm/emgd/emgd/display/dsp/tnc/dsp_tnc.c
new file mode 100644
index 0000000..0697657
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/dsp/tnc/dsp_tnc.c
@@ -0,0 +1,542 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: dsp_tnc.c
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#include <io.h>
+#include <memory.h>
+
+#include <igd.h>
+#include <igd_mode.h>
+#include <igd_pwr.h>
+
+#include <mode.h>
+#include <utils.h>
+
+#include <tnc/regs.h>
+#include <tnc/context.h>
+
+#include "../cmn/dsp_dispatch.h"
+
+#ifdef CONFIG_TNC
+
+extern igd_framebuffer_info_t fb_info_cmn[];
+
+/*
+ * NOTE: Some of these format lists are shared with GMM. For this reason
+ * they cannot be static.
+ */
+unsigned long fb_pixel_formats_tnc[] = {
+	IGD_PF_ARGB32,
+	IGD_PF_xRGB32,
+	IGD_PF_ABGR32,
+	IGD_PF_ARGB32_2101010,
+	IGD_PF_RGB16_565,
+	IGD_PF_ARGB8_INDEXED,
+	0
+};
+
+unsigned long vga_pixel_formats_tnc[] = {
+	IGD_PF_ARGB8_INDEXED,
+	0
+};
+
+#ifndef CONFIG_MICRO
+unsigned long sprite_pixel_formats_tnc[] = {
+	IGD_PF_ARGB32,
+	IGD_PF_ABGR32,
+	IGD_PF_ARGB32_2101010,
+	IGD_PF_RGB16_565,
+	IGD_PF_ARGB8_INDEXED,
+	IGD_PF_YUV422_PACKED_YUY2,
+	IGD_PF_YUV422_PACKED_UYVY,
+	0
+};
+
+unsigned long render_pixel_formats_tnc[] = {
+	IGD_PF_ARGB32,
+	IGD_PF_xRGB32,
+	IGD_PF_ARGB32_2101010,
+	IGD_PF_RGB16_565,
+	IGD_PF_xRGB16_555,
+	IGD_PF_ARGB16_1555,
+	IGD_PF_ARGB16_4444,
+	IGD_PF_YUV422_PACKED_YUY2,
+	IGD_PF_YUV422_PACKED_UYVY,
+	IGD_PF_R16F,
+	IGD_PF_GR32_1616F,
+	IGD_PF_R32F,
+	IGD_PF_ABGR64_16161616F,
+	IGD_PF_YUV420_PLANAR_NV12,
+	IGD_PF_YUV410_PLANAR_YVU9,
+	0
+};
+
+unsigned long texture_pixel_formats_tnc[] = {
+	IGD_PF_ARGB32,
+	IGD_PF_xRGB32,
+	IGD_PF_ABGR32,
+	IGD_PF_xBGR32,
+	IGD_PF_RGB16_565,
+	IGD_PF_xRGB16_555,
+	IGD_PF_ARGB16_1555,
+	IGD_PF_ARGB16_4444,
+	IGD_PF_ARGB8_INDEXED,
+	IGD_PF_YUV422_PACKED_YUY2,
+	IGD_PF_YUV422_PACKED_UYVY,
+	IGD_PF_YUV420_PLANAR_I420,
+	IGD_PF_YUV420_PLANAR_IYUV,
+	IGD_PF_YUV420_PLANAR_YV12,
+	IGD_PF_YUV410_PLANAR_YVU9,
+	IGD_PF_YUV420_PLANAR_NV12,
+	IGD_PF_DVDU_88,
+	IGD_PF_LDVDU_655,
+	IGD_PF_xLDVDU_8888,
+	IGD_PF_DXT1,
+	IGD_PF_DXT2,
+	IGD_PF_DXT3,
+	IGD_PF_DXT4,
+	IGD_PF_DXT5,
+	IGD_PF_L8,
+	IGD_PF_A8,
+	IGD_PF_AL88,
+	IGD_PF_AI44,
+	IGD_PF_L16,
+	IGD_PF_ARGB32_2101010,
+	IGD_PF_AWVU32_2101010,
+	IGD_PF_QWVU32_8888,
+	IGD_PF_GR32_1616,
+	IGD_PF_VU32_1616,
+	IGD_PF_R16F,
+	IGD_PF_GR32_1616F,
+	IGD_PF_R32F,
+	IGD_PF_ABGR64_16161616F,
+	0
+};
+
+unsigned long depth_pixel_formats_tnc[] = {
+	IGD_PF_Z16,
+	IGD_PF_Z24,
+	IGD_PF_S8Z24,
+	0
+};
+
+
+unsigned long cursor_pixel_formats_tnc[] = {
+	IGD_PF_ARGB32,
+	IGD_PF_RGB_2,
+	IGD_PF_RGB_XOR_2,
+	IGD_PF_RGB_T_2,
+	0
+};
+
+unsigned long overlay_pixel_formats_tnc[] = {
+	IGD_PF_YUV422_PACKED_YUY2,
+	IGD_PF_YUV422_PACKED_UYVY,
+	IGD_PF_YUV420_PLANAR_I420,
+	IGD_PF_YUV420_PLANAR_IYUV,
+	IGD_PF_YUV420_PLANAR_YV12,
+	IGD_PF_YUV420_PLANAR_NV12,
+	IGD_PF_YUV410_PLANAR_YVU9,
+	0
+};
+
+unsigned long video_pixel_formats_tnc[] = {
+	IGD_PF_YUV420_PLANAR_NV12,
+	0
+};
+
+unsigned long blt_pixel_formats_tnc[] = {
+	IGD_PF_ARGB32,
+	IGD_PF_xRGB32,
+	IGD_PF_ABGR32,
+	IGD_PF_xBGR32,
+	IGD_PF_RGB16_565,
+	IGD_PF_xRGB16_555,
+	IGD_PF_ARGB16_1555,
+	IGD_PF_ARGB16_4444,
+	IGD_PF_ARGB8_INDEXED,
+	IGD_PF_YUV422_PACKED_YUY2,
+	IGD_PF_YUV422_PACKED_UYVY,
+	IGD_PF_YUV420_PLANAR_I420,
+	IGD_PF_YUV420_PLANAR_IYUV,
+	IGD_PF_YUV420_PLANAR_YV12,
+	IGD_PF_YUV420_PLANAR_NV12,
+	IGD_PF_YUV410_PLANAR_YVU9,
+	IGD_PF_DVDU_88,
+	IGD_PF_LDVDU_655,
+	IGD_PF_xLDVDU_8888,
+	IGD_PF_DXT1,
+	IGD_PF_DXT2,
+	IGD_PF_DXT3,
+	IGD_PF_DXT4,
+	IGD_PF_DXT5,
+	IGD_PF_Z16,
+	IGD_PF_Z24,
+	IGD_PF_S8Z24,
+	IGD_PF_RGB_2,
+	IGD_PF_RGB_XOR_2,
+	IGD_PF_RGB_T_2,
+	IGD_PF_L8,
+	IGD_PF_A8,
+	IGD_PF_AL88,
+	IGD_PF_AI44,
+	IGD_PF_L16,
+	IGD_PF_ARGB32_2101010,
+	IGD_PF_AWVU32_2101010,
+	IGD_PF_QWVU32_8888,
+	IGD_PF_GR32_1616,
+	IGD_PF_VU32_1616,
+	IGD_PF_R16F,
+	IGD_PF_GR32_1616F,
+	IGD_PF_R32F,
+	IGD_PF_ABGR64_16161616F,
+	0
+};
+
+static igd_fb_caps_t caps_table_tnc[] = {
+	{IGD_PF_ARGB32, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+	{IGD_PF_xRGB32, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+	{IGD_PF_ABGR32, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+	{IGD_PF_xBGR32, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+	{IGD_PF_ARGB32_2101010, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+	{IGD_PF_RGB16_565, IGD_CAP_FULL_2D | IGD_CAP_BLEND},
+	{IGD_PF_ARGB8_INDEXED, IGD_CAP_FULL_2D},
+	{0, 0}
+};
+
+#endif
+
+/*
+ * Plane Definitions for Atom E6xx family.
+ */
+static igd_plane_t planea_tnc = {
+	DSPACNTR, IGD_PLANE_DISPLAY | IGD_PLANE_DIH | IGD_PLANE_USE_PIPEA, 0, 0,
+	fb_pixel_formats_tnc, &fb_info_cmn[0], NULL
+};
+
+static igd_plane_t planeb_tnc = {
+	DSPBCNTR, IGD_PLANE_DISPLAY | IGD_PLANE_SPRITE | IGD_PLANE_DIH | IGD_PLANE_USE_PIPEB, 0, 0,
+	fb_pixel_formats_tnc, &fb_info_cmn[1], NULL
+};
+
+static igd_plane_t planec_tnc = {
+	DSPCCNTR, IGD_PLANE_SPRITE, 0, 0,
+	OPT_MICRO_VALUE(sprite_pixel_formats_tnc, NULL), NULL, NULL
+};
+
+static igd_plane_t plane_vga_tnc = {
+	VGACNTRL, IGD_PLANE_VGA, 0, 0,
+	vga_pixel_formats_tnc, NULL, NULL
+};
+
+static igd_plane_t plane_overlay_tnc = {
+	OVADD, IGD_PLANE_OVERLAY, 0, 0,
+	OPT_MICRO_VALUE(overlay_pixel_formats_tnc, NULL), NULL, NULL
+};
+
+static igd_plane_t plane_cursora_tnc = {
+	CUR_A_CNTR, IGD_PLANE_CURSOR|IGD_CURSOR_USE_PIPEA|IGD_CURSOR_USE_PIPEB, 0,0,
+	OPT_MICRO_VALUE(cursor_pixel_formats_tnc, NULL), NULL, NULL
+};
+
+static igd_plane_t plane_cursorb_tnc = {
+	CUR_B_CNTR, IGD_PLANE_CURSOR|IGD_CURSOR_USE_PIPEA|IGD_CURSOR_USE_PIPEB, 0,0,
+	OPT_MICRO_VALUE(cursor_pixel_formats_tnc, NULL), NULL, NULL
+};
+
+/*
+ * Plane lists for Atom E6xx family members.
+ */
+/* Two Main Plane, One Sprite, One VGA, One Overlay, Two Cursor */
+static igd_plane_t *plane_table_tnc[] = {
+	&planea_tnc,
+	&planeb_tnc,
+	&planec_tnc,
+	&plane_vga_tnc,
+	&plane_overlay_tnc,
+	&plane_cursora_tnc,
+	&plane_cursorb_tnc,
+	NULL
+};
+
+static igd_clock_t clock_a_tnc = {
+	DPLLACNTR, FPA0, 17
+};
+
+static igd_clock_t clock_b_tnc = {
+	DPLLBCNTR, FPB0, 16
+};
+
+/*
+ * Pipe definitions for Atom E6xx family.
+ * Pipe A is always tied to LVDS and Pipe B always to SDVO
+ */
+static igd_display_pipe_t pipea_tnc = {
+	0, PIPEA_CONF, PIPEA_TIMINGS, DPALETTE_A, &clock_a_tnc,
+	(IGD_PIPE_IS_PIPEA | IGD_PORT_SHARE_LVDS),
+	0, 0,{NULL, NULL, NULL}, 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/drivers/gpu/drm/emgd/emgd/display/mode/cmn/igd_mode.c b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/igd_mode.c
new file mode 100755
index 0000000..70de834
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/igd_mode.c
@@ -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/drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.c b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.c
new file mode 100755
index 0000000..4db71aa
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.c
@@ -0,0 +1,1347 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: match.c
+ * $Revision: 1.12 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+
+#define CURSOR_DEFAULT_WIDTH	64
+#define CURSOR_DEFAULT_HEIGHT	64
+
+#include <context.h>
+#include <igd_init.h>
+#include <io.h>
+#include <memory.h>
+#include <edid.h>
+#include <pi.h>
+
+#include <igd_mode.h>
+#include <igd_errno.h>
+
+#include <mode.h>
+#include <config.h>
+
+#include "match.h"
+
+
+#define MATCH_MOD(x)  ((x>0)?x:-x)
+#define MATCH_EXACT    0x01
+#define MATCH_NATIVE   0x02
+#define MATCH_CENTER   0x10
+#define MATCH_FOR_VGA  0x20
+
+extern igd_timing_info_t vga_timing_table[];
+extern igd_timing_info_t crt_timing_table[];
+static igd_timing_info_t scaled_timing[IGD_MAX_PIPES];
+
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/* Local variables */
+#ifndef CONFIG_MICRO
+igd_cursor_info_t default_cursor = {
+	CURSOR_DEFAULT_WIDTH,
+	CURSOR_DEFAULT_HEIGHT,
+	CONFIG_DEFAULT_PF,
+	0, 0, 0, 0, 0, 0,
+	0, 0, {0, 0, 0, 0}, IGD_CURSOR_ON, 0, 0, 0, 0
+};
+
+/*!
+ *
+ * @param cursor_info
+ * @param display
+ *
+ * @return -IGD_INVAL on failure
+ * @return 0 on success
+ */
+int validate_cursor(igd_cursor_info_t *cursor_info,
+	igd_display_context_t *display)
+{
+	unsigned long *list_pfs;
+	igd_display_pipe_t *pipe = (igd_display_pipe_t *)(display->pipe);
+
+	EMGD_TRACE_ENTER;
+	if (pipe) {
+		if (pipe->cursor) {
+			list_pfs = pipe->cursor->pixel_formats;
+
+			while (*list_pfs) {
+				if (cursor_info->pixel_format == *list_pfs) {
+					return 0;
+				}
+				list_pfs++;
+			}
+		}
+	}
+
+	EMGD_TRACE_EXIT;
+	return -IGD_INVAL;
+}
+#endif
+
+/*!
+ *
+ * @param timing
+ * @param pt_info
+ *
+ * @return void
+ */
+static void fill_pt(
+	igd_timing_info_t *timing,
+	pigd_display_info_t pt_info)
+{
+	unsigned long flags;
+
+	EMGD_DEBUG("fill_pt Entry");
+
+	/* preserve existing pt_info flags */
+	flags = pt_info->flags;
+
+	/* Simply memcpy the structures and fix up the flags */
+	OS_MEMCPY(pt_info, timing, sizeof(igd_timing_info_t));
+
+	pt_info->flags |= flags;
+
+	/* pt_info doesn't require a IGD_MODE_VESA flag, so clear IGD_MODE_VESA
+	 * Setting this flag creates issues in match mode. */
+	pt_info->flags &= ~IGD_MODE_VESA;
+	return;
+}
+
+
+
+/*!
+ *
+ * @param emgd_encoder
+ * @param timing_table
+ * @param pt_info
+ * @param type
+ *
+ * @return NULL on failure
+ * @return timing on success
+ */
+igd_timing_info_t *kms_match_resolution(
+		emgd_encoder_t *emgd_encoder,
+		igd_timing_info_t *timing_table,
+		igd_display_info_t *pt_info,
+		int type)
+{
+	struct drm_device  *dev          = NULL;
+	igd_timing_info_t  *timing       = NULL;
+	igd_timing_info_t  *match        = NULL;
+	igd_timing_info_t  *native_match = NULL;
+	struct drm_encoder *encoder      = NULL;
+	igd_display_port_t *port         = NULL;
+	struct drm_crtc    *crtc         = NULL;
+	emgd_crtc_t        *emgd_crtc    = NULL;
+	igd_display_pipe_t *pipe         = NULL;
+
+	EMGD_TRACE_ENTER;
+
+	EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
+		pt_info->width, pt_info->height, pt_info->refresh,
+		pt_info->mode_number);
+
+	encoder = &emgd_encoder->base;
+	dev = encoder->dev;
+	timing = timing_table;
+	port = emgd_encoder->igd_port;
+	match = NULL;
+
+	/*
+	 * Note on Native matching.
+	 * The Ideal thing is for a fp_native_dtd to already be marked as such.
+	 * If there is no native timing indicated then we must choose what is
+	 * most likely correct.
+	 * If the mode is not VGA then we should choose any DTD that closely
+	 * matches the mode being set. Failing that we should choose any timing
+	 * that closely matches the mode.
+	 * If the mode is VGA then we should take the current mode as it is
+	 * more likely correct.
+	 */
+	if(type == MATCH_NATIVE) {
+		if(port->fp_native_dtd) {
+			EMGD_DEBUG("Returning quick with a native match");
+
+			EMGD_DEBUG("NATIVE Width=%d, height=%d, refresh=%d mode_num=0x%x",
+				port->fp_native_dtd->width, port->fp_native_dtd->height,
+				port->fp_native_dtd->refresh, port->fp_native_dtd->mode_number);
+
+			return port->fp_native_dtd;
+		}
+		if((pt_info->flags & IGD_MODE_VESA) &&
+			(pt_info->mode_number <= 0x13)) {
+
+			list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+				if (crtc == encoder->crtc) {
+					emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+					pipe = emgd_crtc->igd_pipe;
+					if(pipe->timing) {
+						native_match = pipe->timing;
+					}
+				}
+			}
+		}
+	}
+
+	while (timing->width != IGD_TIMING_TABLE_END) {
+		if(!(timing->mode_info_flags & IGD_MODE_SUPPORTED)) {
+			timing++;
+			continue;
+		}
+
+		if(type == MATCH_NATIVE) {
+			if(timing->mode_info_flags & IGD_MODE_DTD_FP_NATIVE) {
+				port->fp_native_dtd = timing;
+				return timing;
+			}
+
+			if(port->fp_info) {
+				/*
+				 * We may have only fp_width and fp_height which is really
+				 * not enough information to be useful. If we find a
+				 * matching width and height we'll keep the first one while
+				 * still hoping to find an actual native mode later.
+				 */
+				if(!match &&
+					(port->fp_info->fp_width ==
+						(unsigned long)timing->width) &&
+					(port->fp_info->fp_height ==
+						(unsigned long)timing->height)) {
+					match = timing;
+				}
+			} else {
+				/*
+				 * Keep a match because in the event that we never find a
+				 * native DTD then we will just take the exact match.
+				 */
+				if(!match &&
+					(timing->width == pt_info->width) &&
+					(timing->height == pt_info->height) &&
+					(timing->refresh == pt_info->refresh)) {
+					match = timing;
+				}
+			}
+
+			/*
+			 * If it is a DTD then keep it only if it is better than any
+			 * found before.
+			 */
+			if(timing->mode_info_flags & IGD_MODE_DTD_USER) {
+				if(native_match) {
+					if(MATCH_MOD((int)(pt_info->width*pt_info->height) -
+							(native_match->width * native_match->height)) >
+						MATCH_MOD((int)(pt_info->width*pt_info->height) -
+							(timing->width*timing->height))) {
+						native_match = timing;
+					}
+				} else {
+					native_match = timing;
+				}
+			}
+		} else if (type == MATCH_EXACT) {
+			/*
+			 * Looking for an exact match. For VGA/VESA it must match
+			 * mode number. Otherwise it must match width, height, refresh
+			 * etc.
+			 */
+			if(pt_info->flags & IGD_MODE_VESA) {
+				/* ((timing->mode_info_flags & IGD_MODE_VESA)) */
+				if((pt_info->mode_number == timing->mode_number) &&
+					(!pt_info->refresh ||
+						(pt_info->refresh == timing->refresh))) {
+					match = timing;
+					break;
+				}
+			} else {
+				/* If exact match found, then break the loop */
+				if((timing->width == pt_info->width) &&
+					(timing->height == pt_info->height) &&
+					(timing->refresh == pt_info->refresh) &&
+					(
+						(timing->mode_info_flags &
+							(IGD_SCAN_INTERLACE|IGD_PIXEL_DOUBLE|
+								IGD_LINE_DOUBLE)) ==
+						(pt_info->flags &
+							(IGD_SCAN_INTERLACE|IGD_PIXEL_DOUBLE|
+								IGD_LINE_DOUBLE)))) {
+					match = timing;
+
+					/* If exact match found, then break the loop */
+					if ((timing->mode_info_flags & PD_MODE_DTD_USER) ||
+						(timing->mode_info_flags & PD_MODE_DTD)) {
+						break;
+					}
+				}
+			}
+		}
+
+
+		/* Center needs only to be bigger. Aspect ratio doesn't matter. */
+		/*
+		 * Note: The timings have to be big enough to fit the pt_info
+		 * including any pixel double flags. VGA modes will sometimes be
+		 * pixel doubled and need to be centered in a pipe that is double
+		 * in size.
+		 *
+		 * Note2: 720x400 VGA modes can be centered in 640x480 with a
+		 * special hardware config that drops every 9th pixel. Only do
+		 * this when requested.
+		 */
+		else if(type & MATCH_CENTER) {
+			unsigned short eff_width = pt_info->width;
+			unsigned short eff_height = pt_info->height;
+
+			if(type & MATCH_FOR_VGA) {
+				/*
+				 * 720x400 is a magic mode that means all VGA modes are supported
+				 * always use that mode for centering if found.
+				 */
+				if((timing->width == 720) && (timing->height == 400)) {
+					EMGD_DEBUG("Returning with a magic VGA mode");
+					return timing;
+				}
+				if(pt_info->flags & IGD_PIXEL_DOUBLE) {
+					eff_width *= 2;
+				}
+				if(pt_info->flags & IGD_LINE_DOUBLE) {
+					eff_height *= 2;
+				}
+				if((eff_width == 720) &&
+					(port->port_features & IGD_VGA_COMPRESS)) {
+					eff_width = 640;
+				}
+			}
+
+			if((timing->width >= eff_width) &&
+				(timing->height >= eff_height) &&
+				(timing->mode_info_flags & IGD_SCAN_INTERLACE) ==
+				(pt_info->flags & IGD_SCAN_INTERLACE)) {
+				if(match) {
+					/* Check for tighter fit */
+					if((match->width > timing->width) ||
+						(match->height > timing->height)) {
+						match = timing;
+					}
+					/* Try to match refreshrate as well */
+					if((match->width == timing->width) &&
+					   (match->height == timing->height) &&
+					   (pt_info->refresh == timing->refresh)){
+						match = timing;
+					}
+				} else {
+					match = timing;
+				}
+			}
+		}
+		timing++;
+	}
+
+	if(native_match) {
+		EMGD_DEBUG("Returning with a native match");
+		EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
+			native_match->width, native_match->height, native_match->refresh,
+			native_match->mode_number);
+		return native_match;
+	}
+	if (!match) {
+		EMGD_DEBUG("Returning with NO match");
+		return NULL;
+	}
+
+	EMGD_DEBUG("Returning with a match");
+	EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
+		match->width, match->height, match->refresh, match->mode_number);
+	return match;
+} /* end match_resolution */
+
+
+
+/*!
+ * Match the fb and pt structures to a Mode Structure from the table.
+ * When a mode is found update the input structures to reflect the
+ * values found.
+ *
+ * If the frambuffer is smaller than the timings requested, then we
+ * modify the timings so that the framebuffer will be centered.  That is,
+ * unless we are asked to upscale the framebuffer to fit the timings requested.
+ *
+ * In the case of LVDS both centering and scaling can happen. If the mode
+ * is in the list it will be scaled to the Native Timings. If the mode
+ * is not in the list (common or VGA) it will be centered in the next larger
+ * supported mode and then scaled to the native timings.
+ *
+ * Centering is always indicated by returning the timings that should be
+ * programmed to the pipe. The timings will then have their extension pointer
+ * set to point to the centered timings. For centering with scaling the
+ * first extension pointer will contain the scalable timings and the
+ * second will contain the centering timings. The static "scaled_timings"
+ * data structure will be used when the scaled timings need to be
+ * created on the fly due to a framebuffer that is smaller than the
+ * timings.
+ *
+ * FIXME: There is a lot of mentioning of VGA modes in this function from
+ * an earlier implementation of this feature.  The VGA-related code may
+ * not be relevant anymore if we are not building the VBIOS.
+ *
+ * @param emgd_encoder [IN]  Encoder expected to have a mode change
+ * @param fb_info      [IN]  Dimension of the FB to be displayed
+ * @param timing       [OUT] Best matched timing
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+int kms_match_mode (
+	emgd_encoder_t *emgd_encoder,
+	igd_framebuffer_info_t *fb_info,
+	igd_timing_info_t **timing)
+{
+	struct drm_device  *dev;
+	struct drm_encoder *encoder;
+	igd_display_port_t *port;
+	igd_timing_info_t  *timing_table;
+	igd_timing_info_t  *exact_timing  = NULL;
+	igd_timing_info_t  *pipe_timing   = NULL;
+	igd_timing_info_t  *user_timing   = NULL;
+	igd_timing_info_t  *native_timing = NULL;
+	igd_timing_info_t  *vga_timing    = NULL;
+	igd_timing_info_t  *vesa_timing   = NULL;
+	igd_display_info_t *pt_info       = NULL;
+	struct drm_crtc    *crtc          = NULL;
+	emgd_crtc_t        *emgd_crtc     = NULL;
+	igd_display_pipe_t *pipe          = NULL;
+	short               cntr_dff_w    = 0;
+	short               cntr_dff_h    = 0;
+	unsigned long       upscale       = 0;
+
+	EMGD_TRACE_ENTER;
+
+
+	encoder      = &emgd_encoder->base;
+	dev          = encoder->dev;
+	port         = emgd_encoder->igd_port;
+	pt_info      = port->pt_info;
+	timing_table = port->timing_table;
+
+	if(!pt_info) {
+		EMGD_ERROR("NULL Port info detected, returning");
+		return -IGD_ERROR_INVAL;
+	}
+
+	/* Check for default case */
+	if (!(pt_info->flags & IGD_MODE_VESA) &&
+		(pt_info->width == 0) && (pt_info->height == 0)) {
+		EMGD_DEBUG("Display Info width, height are zero, using default case");
+		pt_info->width  = CONFIG_DEFAULT_WIDTH;
+		pt_info->height = CONFIG_DEFAULT_HEIGHT;
+	}
+
+	EMGD_DEBUG("Checking for exact mode match");
+	exact_timing = kms_match_resolution(emgd_encoder, timing_table, pt_info,
+		MATCH_EXACT);
+
+	/*
+	 * At this point we have one of these cases:
+	 *  1) Found an exact match, VGA, VESA or other.
+	 *    -> Go check for FB centering and finish up.
+	 *  2) Found nothing
+	 *    -> Check for VGA/VESA mode to center.
+	 *    -> Check common modes.
+	 */
+	if(exact_timing) {
+		pipe_timing = exact_timing;
+		user_timing = exact_timing;
+		pipe_timing->extn_ptr = NULL;
+	} else {
+		/* No match found? Is it VGA? */
+		if( (pt_info->flags & IGD_MODE_VESA) &&
+			(pt_info->mode_number < 0x1D)    ){
+			EMGD_DEBUG("Checking for exact match in VGA table");
+			/* this only happens if it was a VGA mode number */
+			pt_info->refresh = 0;
+			vga_timing = kms_match_resolution(emgd_encoder, vga_timing_table,
+				pt_info, MATCH_EXACT);
+
+			if(!vga_timing) {
+				return -IGD_ERROR_INVAL;
+			}
+
+			vga_timing->extn_ptr = NULL;
+			/* We got something sane that needs to be centered */
+			user_timing = vga_timing;
+			fill_pt(vga_timing,pt_info);
+
+			/* continue at the bottom where we have
+			 * pipe_timing = NULL, so we will look
+			 * for centered timings for pt_info and
+			 * use cmn_vga_timings to tell kms_match_resolution
+			 * to take into account special VGA mode
+			 * centering regulations
+			 */
+		}
+	}
+
+	/* Find UPSCALING attr value
+	 * this PI func will not modify value of upscale if attr does not exist */
+	pi_pd_find_attr_and_value(port,
+			PD_ATTR_ID_PANEL_FIT,
+			0,/*no PD_FLAG for UPSCALING */
+			NULL, /* dont need the attr ptr*/
+			&upscale);
+
+
+	if(!pipe_timing){
+		/* At this point, one of 2 things has happenned:
+		 *      - we have a mode request that we could not match exactly.
+		 *        and it WASNT a VESA_MODE number request.
+		 *      - we have a request based on VESA_MODE number (maybe from
+		 *        VBIOS IAL) and we could not get a exact match from the
+		 *        port_timing_table, but we did get a match from the vga-
+		 *        timing_table.
+		 * In this case, there is one thing to do - MATCH_CENTER. Match
+		 * resolution will handle it this way:
+		 *      - if its VESA MODE number based, we only need to get
+		 *        the best (tightest) match if its VGA OR DONT match
+		 *        if its one of those magic timings
+		 *      - Else, we need to get the best (tightest) match, AND
+		 *        we need to center requested timings in that tightest fitting
+		 *        timing. But wait! This could mean if the requested pt_info
+		 *        is bigger than anything in the port timing table, we have
+		 *        no choice but to fail.
+		 */
+		unsigned char match_type = MATCH_CENTER;
+
+		EMGD_DEBUG("Checking for a safe centered match");
+		if(vga_timing) {
+			match_type |= MATCH_FOR_VGA;
+		} else if(pt_info->flags & IGD_MODE_VESA) {
+			/* if a vesa mode number was requested...
+			 * and we are centering that mode, we
+			 * need to get the common mode fb size
+			 * in case we need it later for VBIOS
+			 * which doesnt populate the FBInfo
+			 */
+			vesa_timing = kms_match_resolution(emgd_encoder, crt_timing_table,
+				pt_info, MATCH_EXACT);
+		}
+
+		if (upscale && vga_timing) {
+			/* If port supports upscaling and match is called for VGA,
+			 * then center vga mode resolution directly in the native mode
+			 * instead of centering VGA in another resolution */
+			pipe_timing = vga_timing;
+		} else {
+			pipe_timing = kms_match_resolution(emgd_encoder, timing_table,
+							pt_info, match_type);
+			/* This can happen if there is a spurious pt_info from IAL */
+			if (!pipe_timing) {
+				return -IGD_ERROR_INVAL;
+			}
+			pipe_timing->extn_ptr = vga_timing;
+			/* for the case of non VGA mode call,
+			 * at this point, vga_timing is NULL
+			 */
+		}
+
+		if(!vga_timing) {
+			user_timing = pipe_timing;
+		}
+	}
+
+	/*
+	 * At this point pipe_timing is what we are going to program the
+	 * pipe to roughly speaking. If there is a common timing then we
+	 * want it centered in the pipe_timing.
+	 *
+	 * If the framebuffer is smaller than the timings then we need to
+	 * generate a centered set of timings by copying the pipe timings
+	 * and shifting them a bit.
+	 *
+	 * If fb width and height are zero just assume that we want it to
+	 * match the timings and make up a pixel format. This is mostly because
+	 * VGA/VESA modes will just be set by number. We don't know their size
+	 * until we look up the number.
+	 */
+	if(fb_info) {
+		/*
+		 * fb_info is sometimes NULL when just testing something.
+		 */
+		if(!fb_info->pixel_format) {
+			/* Ugly VGA modes, it doesn't matter */
+			fb_info->pixel_format = IGD_PF_ARGB8_INDEXED;
+		}
+		if(!fb_info->width) {
+			if(vga_timing) {
+				fb_info->width = vga_timing->width;
+				fb_info->height = vga_timing->height;
+			} else {
+				if(!vesa_timing){
+					vesa_timing = pipe_timing;
+					/* in case vesa_timing is false set it to
+					 * pipe_timing so we dont need to check for
+					 * validity later, when increasing fb size for
+					 * VBIOS in clone mode (see 18 lines below)
+					 */
+				}
+				fb_info->width = vesa_timing->width;
+				fb_info->height = vesa_timing->height;
+			}
+		}
+
+		/*
+		 * VGA common timings are centered in pipe timings by hardware.
+		 * Otherwise we need to adjust the timings when centering is
+		 * needed.
+		 */
+		if (!vga_timing) {
+			/*
+			 * For VBIOS clone modes the FB should be the biggest mode
+			 * if this is the second match we may need to update the fb
+			 * data structure.
+			 */
+			if(fb_info->flags & IGD_VBIOS_FB) {
+				if ((fb_info->width < vesa_timing->width) ||
+					(fb_info->height < vesa_timing->height)) {
+					fb_info->width = vesa_timing->width;
+					fb_info->height = vesa_timing->height;
+				}
+			}
+
+
+			/* Do centering if fb is smaller than timing except on TV */
+			if ((fb_info->width < pipe_timing->width) ||
+				(fb_info->height < pipe_timing->height)) {
+				unsigned short temp_width = pipe_timing->width;
+				unsigned short temp_height = pipe_timing->height;
+				/* Normally, we should NOT be in here. All IALs only
+				 * are supposed to request for timings that ARE surely
+				 * supported by the HAL,... i.e. query the list of
+				 * supported timings by the port first!
+				 *
+				 * The exception would be if the IAL is purposely
+				 * asking for CENTERING!!! (pt_info's that were not
+				 * part of the supported mode list). This could indicate an
+				 * error or an explicit request for VESA centering!.
+				 */
+
+				/* let's use these 2 variables as flags... and do the
+				 * actual "centering" of the timings later since we do
+				 * also need to acomodate native timings as well
+				 */
+				/* NOTE: we could never be in here in fb_info was NULL */
+				cntr_dff_w = (pipe_timing->width  - fb_info->width)  / 2;
+				cntr_dff_h = (pipe_timing->height - fb_info->height) / 2;
+
+				/* Dont forget to use a different storage sice we dont
+				 * want to change the original (and to be used later)
+				 * ports mode list timings
+				 */
+				list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+					if (crtc == encoder->crtc) {
+						emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+						pipe = emgd_crtc->igd_pipe;
+
+						OS_MEMCPY(&scaled_timing[(pipe->pipe_num)],
+							pipe_timing, sizeof(igd_timing_info_t));
+						pipe_timing = &scaled_timing[(pipe->pipe_num)];
+					}
+				}
+
+				if(port->pd_type != PD_DISPLAY_TVOUT ) {
+					/* TV display don't like changed pipe actives,
+					 * Updating syncs work for TV centering */
+					if (fb_info->width < temp_width) {
+						pipe_timing->width = (unsigned short)fb_info->width;
+						pipe_timing->hblank_start -= cntr_dff_w;
+						pipe_timing->hblank_end   -= cntr_dff_w;
+					}
+
+					if (fb_info->height < temp_height) {
+						pipe_timing->height = (unsigned short)fb_info->height;
+						pipe_timing->vblank_start -= cntr_dff_h;
+						pipe_timing->vblank_end   -= cntr_dff_h;
+					}
+				}
+
+				if (fb_info->width < temp_width) {
+					pipe_timing->hsync_start -= cntr_dff_w;
+					pipe_timing->hsync_end   -= cntr_dff_w;
+				}
+
+				if (fb_info->height < temp_height) {
+					pipe_timing->vsync_start -= cntr_dff_h;
+					pipe_timing->vsync_end   -= cntr_dff_h;
+				}
+			}
+		}
+	}
+
+	if(upscale) {
+		/* Get the native timings */
+		EMGD_DEBUG("Checking for Native LVDS match for scaling");
+		native_timing = kms_match_resolution(emgd_encoder, timing_table,
+							pt_info, MATCH_NATIVE);
+		if(native_timing && (native_timing != pipe_timing)) {
+			native_timing->extn_ptr = pipe_timing;
+			pipe_timing = native_timing;
+		}
+	}
+
+	/*
+	 * Match mode returns as follows:
+	 * In case of VGA setmode:
+	 * 1) We will end up with either:
+	 *   magic->vga   ---   For displays supports native VGA
+	 *      or
+	 *   native->vga  ---   Upscaling displays
+	 *      or
+	 *   pipe->vga    ---   For other displays
+	 *
+	 * 2) In case of regular setmode:
+	 *   pipe         ---   For regular displays
+	 *      or
+	 *   native->vesa ---   Upscaling displays
+	 *
+	 *   Note: 1) Here "pipe" can be munged if centering is required.
+	 *         2) "vesa" is the requested mode, native is the native timing
+	 *            of the display.
+	 */
+
+	/*
+	 * Update Input Structures with values found
+	 * Note: This might not be what is going to be programmed. It is what
+	 * the user thinks they set. Scaling or centering could have altered
+	 * that.
+	 */
+	fill_pt(user_timing, pt_info);
+	*timing = pipe_timing;
+	EMGD_TRACE_EXIT;
+
+	return 0;
+}
+
+
+/*!
+ *
+ * @param display
+ * @param timing_table
+ * @param pt_info
+ * @param type
+ *
+ * @return NULL on failure
+ * @return timing on success
+ */
+static igd_timing_info_t *match_resolution(
+		igd_display_context_t *display,
+		igd_timing_info_t *timing_table,
+		igd_display_info_t *pt_info,
+		int type)
+{
+	igd_timing_info_t *timing;
+	igd_timing_info_t *match;
+	igd_timing_info_t *native_match = NULL;
+	igd_display_port_t *port;
+
+	EMGD_DEBUG("Enter match_resolution");
+
+	EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
+		pt_info->width, pt_info->height, pt_info->refresh,
+		pt_info->mode_number);
+
+	timing = timing_table;
+	match = NULL;
+	port = PORT_OWNER(display);
+
+	/*
+	 * Note on Native matching.
+	 * The Ideal thing is for a fp_native_dtd to already be marked as such.
+	 * If there is no native timing indicated then we must choose what is
+	 * most likely correct.
+	 * If the mode is not VGA then we should choose any DTD that closely
+	 * matches the mode being set. Failing that we should choose any timing
+	 * that closely matches the mode.
+	 * If the mode is VGA then we should take the current mode as it is
+	 * more likely correct.
+	 */
+	if(type == MATCH_NATIVE) {
+		if(port->fp_native_dtd) {
+			EMGD_DEBUG("Returning quick with a native match");
+
+			EMGD_DEBUG("NATIVE Width=%d, height=%d, refresh=%d mode_num=0x%x",
+				port->fp_native_dtd->width, port->fp_native_dtd->height,
+				port->fp_native_dtd->refresh, port->fp_native_dtd->mode_number);
+
+			return port->fp_native_dtd;
+		}
+		if((pt_info->flags & IGD_MODE_VESA) &&
+			(pt_info->mode_number <= 0x13)) {
+			if(PIPE(display)->timing) {
+				native_match = PIPE(display)->timing;
+			}
+		}
+	}
+
+	while (timing->width != IGD_TIMING_TABLE_END) {
+		if(!(timing->mode_info_flags & IGD_MODE_SUPPORTED)) {
+			timing++;
+			continue;
+		}
+
+		if(type == MATCH_NATIVE) {
+			if(timing->mode_info_flags & IGD_MODE_DTD_FP_NATIVE) {
+				port->fp_native_dtd = timing;
+				return timing;
+			}
+
+			if(port->fp_info) {
+				/*
+				 * We may have only fp_width and fp_height which is really
+				 * not enough information to be useful. If we find a
+				 * matching width and height we'll keep the first one while
+				 * still hoping to find an actual native mode later.
+				 */
+				if(!match &&
+					(port->fp_info->fp_width ==
+						(unsigned long)timing->width) &&
+					(port->fp_info->fp_height ==
+						(unsigned long)timing->height)) {
+					match = timing;
+				}
+			} else {
+				/*
+				 * Keep a match because in the event that we never find a
+				 * native DTD then we will just take the exact match.
+				 */
+				if(!match &&
+					(timing->width == pt_info->width) &&
+					(timing->height == pt_info->height) &&
+					(timing->refresh == pt_info->refresh)) {
+					match = timing;
+				}
+			}
+
+			/*
+			 * If it is a DTD then keep it only if it is better than any
+			 * found before.
+			 */
+			if(timing->mode_info_flags & IGD_MODE_DTD_USER) {
+				if(native_match) {
+					if(MATCH_MOD((int)(pt_info->width*pt_info->height) -
+							(native_match->width * native_match->height)) >
+						MATCH_MOD((int)(pt_info->width*pt_info->height) -
+							(timing->width*timing->height))) {
+						native_match = timing;
+					}
+				} else {
+					native_match = timing;
+				}
+			}
+		} else if (type == MATCH_EXACT) {
+			/*
+			 * Looking for an exact match. For VGA/VESA it must match
+			 * mode number. Otherwise it must match width, height, refresh
+			 * etc.
+			 */
+			if(pt_info->flags & IGD_MODE_VESA) {
+				/* ((timing->mode_info_flags & IGD_MODE_VESA)) */
+				if((pt_info->mode_number == timing->mode_number) &&
+					(!pt_info->refresh ||
+						(pt_info->refresh == timing->refresh))) {
+					match = timing;
+					break;
+				}
+			} else {
+				/* If exact match found, then break the loop */
+				if((timing->width == pt_info->width) &&
+					(timing->height == pt_info->height) &&
+					(timing->refresh == pt_info->refresh) &&
+					(
+						(timing->mode_info_flags &
+							(IGD_SCAN_INTERLACE|IGD_PIXEL_DOUBLE|
+								IGD_LINE_DOUBLE)) ==
+						(pt_info->flags &
+							(IGD_SCAN_INTERLACE|IGD_PIXEL_DOUBLE|
+								IGD_LINE_DOUBLE)))) {
+					match = timing;
+
+					/* If exact match found, then break the loop */
+					if ((timing->mode_info_flags & PD_MODE_DTD_USER) ||
+						(timing->mode_info_flags & PD_MODE_DTD)) {
+						break;
+					}
+				}
+			}
+		}
+
+
+		/* Center needs only to be bigger. Aspect ratio doesn't matter. */
+		/*
+		 * Note: The timings have to be big enough to fit the pt_info
+		 * including any pixel double flags. VGA modes will sometimes be
+		 * pixel doubled and need to be centered in a pipe that is double
+		 * in size.
+		 *
+		 * Note2: 720x400 VGA modes can be centered in 640x480 with a
+		 * special hardware config that drops every 9th pixel. Only do
+		 * this when requested.
+		 */
+		else if(type & MATCH_CENTER) {
+			unsigned short eff_width = pt_info->width;
+			unsigned short eff_height = pt_info->height;
+
+			if(type & MATCH_FOR_VGA) {
+				/*
+				 * 720x400 is a magic mode that means all VGA modes are supported
+				 * always use that mode for centering if found.
+				 */
+				if((timing->width == 720) && (timing->height == 400)) {
+					EMGD_DEBUG("Returning with a magic VGA mode");
+					return timing;
+				}
+				if(pt_info->flags & IGD_PIXEL_DOUBLE) {
+					eff_width *= 2;
+				}
+				if(pt_info->flags & IGD_LINE_DOUBLE) {
+					eff_height *= 2;
+				}
+				if((eff_width == 720) &&
+					(port->port_features & IGD_VGA_COMPRESS)) {
+					eff_width = 640;
+				}
+			}
+
+			if((timing->width >= eff_width) &&
+				(timing->height >= eff_height) &&
+				(timing->mode_info_flags & IGD_SCAN_INTERLACE) ==
+				(pt_info->flags & IGD_SCAN_INTERLACE)) {
+				if(match) {
+					/* Check for tighter fit */
+					if((match->width > timing->width) ||
+						(match->height > timing->height)) {
+						match = timing;
+					}
+					/* Try to match refreshrate as well */
+					if((match->width == timing->width) &&
+					   (match->height == timing->height) &&
+					   (pt_info->refresh == timing->refresh)){
+						match = timing;
+					}
+				} else {
+					match = timing;
+				}
+			}
+		}
+		timing++;
+	}
+
+	if(native_match) {
+		EMGD_DEBUG("Returning with a native match");
+		EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
+			native_match->width, native_match->height, native_match->refresh,
+			native_match->mode_number);
+		return native_match;
+	}
+	if (!match) {
+		EMGD_DEBUG("Returning with NO match");
+		return NULL;
+	}
+
+	EMGD_DEBUG("Returning with a match");
+	EMGD_DEBUG("Width=%d, height=%d, refresh=%d mode_number=0x%x",
+		match->width, match->height, match->refresh, match->mode_number);
+	return match;
+} /* end match_resolution */
+
+
+
+/*!
+ * Match the fb and pt structures to a Mode Structure from the table.
+ * When a mode is found update the input structures to reflect the
+ * values found.
+ *
+ * Notes:
+ *  Match mode has several options for what it can do. Foremost it should
+ * attempt to find a mode matching the requested one from the timing table
+ * provided. If the mode requested is not in the list this means one of
+ * two things.
+ *   1) The IAL is calling without checking modes. It is just passing down
+ *  something that a user asked for. This is ok but we need to be safe so
+ *  we return the next smaller mode with the same aspect ratio.
+ *
+ *   2) The IAL is requesting a very common "required" mode even though the
+ *  port doesn't support it. In this case it should be in the static common
+ *  modes table and can be centered in the next larger timings in the
+ *  mode table.
+ *
+ * If the Frambuffer is smaller than the timings requested a fake set of
+ * centered timings is returned to program the pipe.
+ *
+ * In the case of VGA modes. If the mode is in the mode table everything is
+ * fine and we just return that. If it is not in the table we find the next
+ * larger suitable mode and prepare to center in that mode. Using the static
+ * timings from the VGA table as the VGA mode. We do not need to generate
+ * a fake set of timings because VGA will center itself automatically in
+ * hardware.
+ *
+ * In the case of LVDS both centering and scaling can happen. If the mode
+ * is in the list it will be scaled to the Native Timings. If the mode
+ * is not in the list (common or VGA) it will be centered in the next larger
+ * supported mode and then scaled to the native timings.
+ *
+ * Centering is always indicated by returning the timings that should be
+ * programmed to the pipe. The timings will then have their extension pointer
+ * set to point to the centered timings. For centering with scaling the
+ * first extension pointer will contain the scalable timings and the
+ * second will contain the centering timings. The static "scaled_timings"
+ * data structure will be used when the scaled timings need to be
+ * created on the fly due to a Framebuffer that is smaller than the
+ * timings.
+ *
+ * @param display
+ * @param timing_table
+ * @param fb_info
+ * @param pt_info
+ * @param timing
+ *
+ * @return -IGD_ERROR_INVAL on failure
+ * @return 0 on success
+ */
+int match_mode (
+	igd_display_context_t *display,
+	igd_timing_info_t *timing_table,
+	igd_framebuffer_info_t *fb_info,
+	igd_display_info_t *pt_info,
+	igd_timing_info_t **timing)
+{
+	igd_timing_info_t *exact_timing = NULL;
+	igd_timing_info_t *pipe_timing = NULL;
+	igd_timing_info_t *user_timing = NULL;
+	igd_timing_info_t *native_timing = NULL;
+	igd_timing_info_t *vga_timing = NULL;
+	igd_timing_info_t *vesa_timing = NULL;
+	short cntr_dff_w = 0;
+	short cntr_dff_h = 0;
+	unsigned long upscale = 0;
+
+	EMGD_DEBUG("Enter Match Mode");
+
+	if(!pt_info) {
+		EMGD_ERROR("NULL Port info detected, returning");
+		return -IGD_ERROR_INVAL;
+	}
+
+	/* Check for default case */
+	if (!(pt_info->flags & IGD_MODE_VESA) &&
+		(pt_info->width == 0) && (pt_info->height == 0)) {
+		EMGD_DEBUG("Display Info width, height are zero, using default case");
+		pt_info->width = CONFIG_DEFAULT_WIDTH;
+		pt_info->height = CONFIG_DEFAULT_HEIGHT;
+	}
+
+	EMGD_DEBUG("Checking for exact mode match");
+	exact_timing = match_resolution(display, timing_table, pt_info,
+		MATCH_EXACT);
+	/*
+	 * At this point we have one of these cases:
+	 *  1) Found an exact match, VGA, VESA or other.
+	 *    -> Go check for FB centering and finish up.
+	 *  2) Found nothing
+	 *    -> Check for VGA/VESA mode to center.
+	 *    -> Check common modes.
+	 */
+	if(exact_timing) {
+		pipe_timing = exact_timing;
+		user_timing = exact_timing;
+		pipe_timing->extn_ptr = NULL;
+	} else {
+		/* No match found? Is it VGA? */
+		if( (pt_info->flags & IGD_MODE_VESA) &&
+			(pt_info->mode_number < 0x1D)    ){
+			EMGD_DEBUG("Checking for exact match in VGA table");
+			/* this only happens if it was a VGA mode number */
+			pt_info->refresh = 0;
+			vga_timing = match_resolution(display, vga_timing_table,
+				pt_info, MATCH_EXACT);
+
+			if(!vga_timing) {
+				return -IGD_ERROR_INVAL;
+			}
+
+			vga_timing->extn_ptr = NULL;
+			/* We got something sane that needs to be centered */
+			user_timing = vga_timing;
+			fill_pt(vga_timing,pt_info);
+
+			/* continue at the bottom where we have
+			 * pipe_timing = NULL, so we will look
+			 * for centered timings for pt_info and
+			 * use cmn_vga_timings to tell match_resolution
+			 * to take into account special VGA mode
+			 * centering regulations
+			 */
+		}
+	}
+
+	/* Find UPSCALING attr value*/
+	pi_pd_find_attr_and_value(PORT_OWNER(display),
+			PD_ATTR_ID_PANEL_FIT,
+			0,/*no PD_FLAG for UPSCALING */
+			NULL, /* dont need the attr ptr*/
+			&upscale);
+	/* this PI func will not modify value of upscale if attr does not exist */
+
+	if(!pipe_timing){
+		/* At this point, one of 2 things has happenned:
+		 *      - we have a mode request that we could not match exactly.
+		 *        and it WASNT a VESA_MODE number request.
+		 *      - we have a request based on VESA_MODE number (maybe from
+		 *        VBIOS IAL) and we could not get a exact match from the
+		 *        port_timing_table, but we did get a match from the vga-
+		 *        timing_table.
+		 * In this case, there is one thing to do - MATCH_CENTER. Match
+		 * resolution will handle it this way:
+		 *      - if its VESA MODE number based, we only need to get
+		 *        the best (tightest) match if its VGA OR DONT match
+		 *        if its one of those magic timings
+		 *      - Else, we need to get the best (tightest) match, AND
+		 *        we need to center requested timings in that tightest fitting
+		 *        timing. But wait! This could mean if the requested pt_info
+		 *        is bigger than anything in the port timing table, we have
+		 *        no choice but to fail.
+		 */
+		unsigned char match_type = MATCH_CENTER;
+
+		EMGD_DEBUG("Checking for a safe centered match");
+		if(vga_timing) {
+			match_type |= MATCH_FOR_VGA;
+		} else if(pt_info->flags & IGD_MODE_VESA) {
+			/* if a vesa mode number was requested...
+			 * and we are centering that mode, we
+			 * need to get the common mode fb size
+			 * in case we need it later for VBIOS
+			 * which doesnt populate the FBInfo
+			 */
+			vesa_timing = match_resolution(display, crt_timing_table,
+				pt_info, MATCH_EXACT);
+		}
+
+		if (upscale && vga_timing) {
+			/* If port supports upscaling and match is called for VGA,
+			 * then center vga mode resolution directly in the native mode
+			 * instead of centering VGA in another resolution */
+			pipe_timing = vga_timing;
+		} else {
+			pipe_timing = match_resolution(display, timing_table, pt_info,
+				match_type);
+			/* This can happen if there is a spurious pt_info from IAL */
+			if (!pipe_timing) {
+				return -IGD_ERROR_INVAL;
+			}
+			pipe_timing->extn_ptr = vga_timing;
+			/* for the case of non VGA mode call,
+			 * at this point, vga_timing is NULL
+			 */
+		}
+
+		if(!vga_timing) {
+			user_timing = pipe_timing;
+		}
+	}
+
+	/*
+	 * At this point pipe_timing is what we are going to program the
+	 * pipe to roughly speaking. If there is a common timing then we
+	 * want it centered in the pipe_timing.
+	 *
+	 * If the framebuffer is smaller than the timings then we need to
+	 * generate a centered set of timings by copying the pipe timings
+	 * and shifting them a bit.
+	 *
+	 * If fb width and height are zero just assume that we want it to
+	 * match the timings and make up a pixel format. This is mostly because
+	 * VGA/VESA modes will just be set by number. We don't know their size
+	 * until we look up the number.
+	 */
+	if(fb_info) {
+		/*
+		 * fb_info is sometimes NULL when just testing something.
+		 */
+		if(!fb_info->pixel_format) {
+			/* Ugly VGA modes, it doesn't matter */
+			fb_info->pixel_format = IGD_PF_ARGB8_INDEXED;
+		}
+		if(!fb_info->width) {
+			if(vga_timing) {
+				fb_info->width = vga_timing->width;
+				fb_info->height = vga_timing->height;
+			} else {
+				if(!vesa_timing){
+					vesa_timing = pipe_timing;
+					/* in case vesa_timing is false set it to
+					 * pipe_timing so we dont need to check for
+					 * validity later, when increasing fb size for
+					 * VBIOS in clone mode (see 18 lines below)
+					 */
+				}
+				fb_info->width = vesa_timing->width;
+				fb_info->height = vesa_timing->height;
+			}
+		}
+
+		/*
+		 * VGA common timings are centered in pipe timings by hardware.
+		 * Otherwise we need to adjust the timings when centering is
+		 * needed.
+		 */
+		if (!vga_timing) {
+			/*
+			 * For VBIOS clone modes the FB should be the biggest mode
+			 * if this is the second match we may need to update the fb
+			 * data structure.
+			 */
+			if(fb_info->flags & IGD_VBIOS_FB) {
+				if ((fb_info->width < vesa_timing->width) ||
+					(fb_info->height < vesa_timing->height)) {
+					fb_info->width = vesa_timing->width;
+					fb_info->height = vesa_timing->height;
+				}
+			}
+
+
+			/* Do centering if fb is smaller than timing except on TV */
+			if ((fb_info->width < pipe_timing->width) ||
+				(fb_info->height < pipe_timing->height)) {
+				unsigned short temp_width = pipe_timing->width;
+				unsigned short temp_height = pipe_timing->height;
+				/* Normally, we should NOT be in here. All IALs only
+				 * are supposed to request for timings that ARE surely
+				 * supported by the HAL,... i.e. query the list of
+				 * supported timings by the port first!
+				 *
+				 * The exception would be if the IAL is purposely
+				 * asking for CENTERING!!! (pt_info's that were not
+				 * part of the supported mode list). This could indicate an
+				 * error or an explicit request for VESA centering!.
+				 */
+
+				/* let's use these 2 variables as flags... and do the
+				 * actual "centering" of the timings later since we do
+				 * also need to acomodate native timings as well
+				 */
+				/* NOTE: we could never be in here in fb_info was NULL */
+				cntr_dff_w = (pipe_timing->width - fb_info->width) / 2;
+				cntr_dff_h = (pipe_timing->height - fb_info->height) / 2;
+
+				/* Dont forget to use a different storage sice we dont
+				 * want to change the original (and to be used later)
+				 * ports mode list timings
+				 */
+				OS_MEMCPY(&scaled_timing[(PIPE(display)->pipe_num)],
+					pipe_timing,
+					sizeof(igd_timing_info_t));
+
+				pipe_timing = &scaled_timing[(PIPE(display)->pipe_num)];
+
+				if(PORT_OWNER(display)->pd_type != PD_DISPLAY_TVOUT ) {
+					/* TV display don't like changed pipe actives,
+					 * Updating syncs work for TV centering */
+					if (fb_info->width < temp_width) {
+						pipe_timing->width = (unsigned short)fb_info->width;
+						pipe_timing->hblank_start -= cntr_dff_w;
+						pipe_timing->hblank_end -= cntr_dff_w;
+					}
+
+					if (fb_info->height < temp_height) {
+						pipe_timing->height = (unsigned short)fb_info->height;
+						pipe_timing->vblank_start -= cntr_dff_h;
+						pipe_timing->vblank_end -= cntr_dff_h;
+					}
+				}
+
+				if (fb_info->width < temp_width) {
+					pipe_timing->hsync_start -= cntr_dff_w;
+					pipe_timing->hsync_end -= cntr_dff_w;
+				}
+
+				if (fb_info->height < temp_height) {
+					pipe_timing->vsync_start -= cntr_dff_h;
+					pipe_timing->vsync_end -= cntr_dff_h;
+				}
+			}
+		}
+	}
+
+	if(upscale) {
+		/* Get the native timings */
+		EMGD_DEBUG("Checking for Native LVDS match for scaling");
+		native_timing = match_resolution(display, timing_table, pt_info,
+			MATCH_NATIVE);
+		if(native_timing && (native_timing != pipe_timing)) {
+			native_timing->extn_ptr = pipe_timing;
+			pipe_timing = native_timing;
+		}
+	}
+
+	/*
+	 * Match mode returns as follows:
+	 * In case of VGA setmode:
+	 * 1) We will end up with either:
+	 *   magic->vga   ---   For displays supports native VGA
+	 *      or
+	 *   native->vga  ---   Upscaling displays
+	 *      or
+	 *   pipe->vga    ---   For other displays
+	 *
+	 * 2) In case of regular setmode:
+	 *   pipe         ---   For regular displays
+	 *      or
+	 *   native->vesa ---   Upscaling displays
+	 *
+	 *   Note: 1) Here "pipe" can be munged if centering is required.
+	 *         2) "vesa" is the requested mode, native is the native timing
+	 *            of the display.
+	 */
+
+	/*
+	 * Update Input Structures with values found
+	 * Note: This might not be what is going to be programmed. It is what
+	 * the user thinks they set. Scaling or centering could have altered
+	 * that.
+	 */
+	fill_pt(user_timing, pt_info);
+	*timing = pipe_timing;
+	EMGD_DEBUG("Return");
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.h b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.h
new file mode 100755
index 0000000..40a6721
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/match.h
@@ -0,0 +1,59 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: match.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains the mode matching algorithms
+ *-----------------------------------------------------------------------------
+ */
+
+#include <mode.h>
+
+int validate_fb(
+	pigd_framebuffer_info_t fb_info,
+	igd_display_plane_t *plane);
+
+int validate_cursor(
+	igd_cursor_info_t *cursor_info,
+	igd_display_context_t *display);
+
+int match_mode (
+	igd_display_context_t *display,
+	igd_timing_info_t *timing_table,
+	igd_framebuffer_info_t *fb_info,
+	igd_display_info_t *pt_info,
+	igd_timing_info_t **timing);
+
+int kms_match_mode (
+	emgd_encoder_t *emgd_encoder,
+	igd_framebuffer_info_t *fb_info,
+	igd_timing_info_t **timing);
+
+igd_timing_info_t *kms_match_resolution(
+	emgd_encoder_t *emgd_encoder,
+	igd_timing_info_t *timing_table,
+	igd_display_info_t *pt_info,
+	int type);
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/cmn/micro_mode.c b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/micro_mode.c
new file mode 100644
index 0000000..5d615aa
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/micro_mode.c
@@ -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/drivers/gpu/drm/emgd/emgd/display/mode/cmn/mode_dispatch.h b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/mode_dispatch.h
new file mode 100644
index 0000000..b2ae62e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/mode_dispatch.h
@@ -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/drivers/gpu/drm/emgd/emgd/display/mode/cmn/vga_mode.c b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/vga_mode.c
new file mode 100644
index 0000000..546b699
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/cmn/vga_mode.c
@@ -0,0 +1,1467 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: vga_mode.c
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains VGA plane/pipe programming functions that can
+ *  be used on any VGA compatible hardware. Hardware specific functions
+ *  should put the device in VGA compatible mode prior to calling thses
+ *  functions.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+#include <context.h>
+
+#include <sched.h>
+
+#include <igd_vga.h>
+
+#include "drm_emgd_private.h"
+
+#include <mode.h>
+#include <utils.h>
+#include <vga.h>
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/*
+ * For mono modes this is 0  (CRTC is at 0x3b4)
+ * For other modes it is 0x20 (CRTC is at 0x3d4)
+ */
+unsigned char vga_port_offset = 0x20;
+
+/* This is a global variable used by the vBIOS to override the mode table
+ * if a User Defined Mode Table is set. */
+vga_mode_data_t FAR (*vga_mode_data_ptr)[]=&vga_mode_data;
+
+/* This is a global variable used by the vBIOS to enable/disable the
+ * loading of the palette during a mode change.  A global variable is
+ * the best choice, since this is not really an OAL interface.
+ *   0=Do load the default palette on a mode change.
+ *   1=Do NOT load the default palette on a mode change. */
+unsigned char vga_disable_default_palette_load = 0;
+
+/*!
+ *
+ * @param mmio
+ * @param port
+ * @param index
+ * @param value
+ *
+ * @return void
+ */
+void write_vga_reg(unsigned char *mmio, unsigned short port,
+	unsigned char index, unsigned char value)
+{
+	WRITE_VGA(mmio, port, index, value);
+}
+
+/*!
+ *
+ * @param display
+ * @param timings
+ *
+ * @return void
+ */
+void kms_program_plane_vga(unsigned char *mmio,
+	igd_timing_info_t *timings)
+{
+
+	EMGD_DEBUG("Enter program_plane_vga");
+
+	/* Set Bit 5 so the plane remains off.  It will be turned on
+	 * in the IAL.  This is necessary, so the clear screen can occur
+	 * before the mode is enabled. */
+	write_vga_reg(mmio, SR_PORT, 0x01,
+		(*vga_mode_data_ptr)[timings->mode_number].sr_regs[0] | 0x20);
+	OS_SLEEP(1000);
+
+	return;
+}
+
+/*!
+ *
+ * @param display
+ * @param timings
+ *
+ * @return void
+ */
+void program_plane_vga(igd_display_context_t *display,
+	igd_timing_info_t *timings)
+{
+	unsigned char *mmio;
+
+	EMGD_DEBUG("Enter program_plane_vga");
+
+	mmio = (unsigned char *)MMIO(display);
+	/* Set Bit 5 so the plane remains off.  It will be turned on
+	 * in the IAL.  This is necessary, so the clear screen can occur
+	 * before the mode is enabled. */
+	write_vga_reg(mmio, SR_PORT, 0x01,
+		(*vga_mode_data_ptr)[timings->mode_number].sr_regs[0] | 0x20);
+	OS_SLEEP(1000);
+
+	return;
+}
+
+unsigned char mono_colors[] = {0x00, 0x2a, 0x00, 0x3f};
+unsigned char normal_colors[] = {0x00, 0x2a, 0x15, 0x3f};
+
+unsigned char mono_color_bits[] = {8,16,8,16,8,16};
+unsigned char p16_color_bits[] = {4,16,2,16,1,16};
+unsigned char p64_color_bits[] = {4,32,2,16,1,8};
+
+/*!
+ *
+ * @param mmio
+ * @param n
+ *
+ * @return void
+ */
+void set_3f_palette(unsigned char *mmio, int n)
+{
+	int i;
+	for(i=0; i<n*3; i++) {
+		EMGD_WRITE8(0x3f, EMGD_MMIO(mmio) + 0x3c9);
+	}
+}
+
+/*!
+ *
+ * @param mmio
+ * @param n
+ * @param bits
+ * @param colors
+ * @param palette_hack
+ *
+ * @return void
+ */
+void set_palette_vga(unsigned char *mmio, int n, unsigned char *bits,
+	unsigned char *colors, unsigned char palette_hack)
+{
+	int i, j;
+	unsigned char *current_bits;
+	unsigned char color;
+
+	for(i=0; i<n; i++) {
+		current_bits = bits;
+		for(j=0; j<3; j++) {
+			color = colors[((i & current_bits[1])?2:0) |
+				((i & current_bits[0])?1:0)];
+			/* Nasty Hack for Special Case VGA palette */
+			if(palette_hack && (color == 0x2a) && (i%8==6) && (j==1)) {
+				color = 0x15;
+			}
+			EMGD_WRITE8( color, EMGD_MMIO(mmio) + 0x3c9);
+			current_bits += 2;
+		}
+	}
+}
+
+/*!
+ *
+ * @param mmio
+ *
+ * @return void
+ */
+void set_256_palette(unsigned char *mmio)
+{
+	unsigned char top_of_range[] = {
+		0x3f, 0x1c, 0x10
+	};
+	unsigned char bottom_of_range[] = {
+		0x00, 0x1f, 0x2d,
+		0x00, 0x0e, 0x14,
+		0x00, 0x08, 0x0b
+	};
+	unsigned char mono_256_color[]={
+		0x00, 0x05, 0x08,
+		0x0B, 0x0E, 0x11,
+		0x14, 0x18, 0x1C,
+		0x20, 0x24, 0x28,
+		0x2D, 0x32, 0x38,
+		0x3F
+	};
+	unsigned char p256_color_bits[] = {4,8,2,8,1,8};
+	unsigned char *bottom = bottom_of_range;
+	unsigned char *top = top_of_range;
+	unsigned char pattern_number[] = {4, 0, 0};
+	unsigned char changing_pattern = 2;
+	unsigned short adder;
+	char diff = 1;
+	int h,i,j,k,l;
+
+	set_palette_vga(mmio, 16, p256_color_bits, normal_colors, 1);
+
+	/* mono data */
+	for(i=0; i<16; i++) {
+		for (j=0; j<3; j++) {
+			EMGD_WRITE8(mono_256_color[i], EMGD_MMIO(mmio) + 0x3c9);
+		}
+	}
+	for(l=0; l<3; l++) {
+		for(k=0; k<3; k++) {
+			/* Adder is in 14.2 fixed point */
+			adder =  *top - *bottom;
+			for(j=0; j<6; j++) {
+				for(i=0; i<4; i++) {
+					for(h=2; h>=0; h--) {
+						EMGD_WRITE8( *bottom + (pattern_number[h]*adder + 1)/4,
+							EMGD_MMIO(mmio) + 0x3c9);
+					}
+					pattern_number[changing_pattern] += diff;
+				}
+				diff = -diff;
+				changing_pattern++;
+				changing_pattern %= 3;
+			}
+			bottom++;
+		}
+		top++;
+	}
+	set_3f_palette(mmio, 8);
+}
+
+static unsigned char next_ar;
+static unsigned char next_cr;
+static unsigned char next_gr;
+static unsigned char *g_mmio;
+
+/*!
+ * This is a little trick to save some space. Write these registers
+ * sequentially to save us a little bit of data space.
+ *
+ * @param value
+ *
+ * @return void
+ */
+void write_next_ar_reg(unsigned char value)
+{
+	WRITE_AR(g_mmio, next_ar, value);
+	next_ar++;
+}
+
+/*!
+ * This is a little trick to save some space. Write these registers
+ * sequentially to save us a little bit of data space.
+ *
+ * @param value
+ *
+ * @return void
+ */
+void write_next_cr_reg(unsigned char value)
+{
+	write_vga_reg(g_mmio, CR_PORT, next_cr, value);
+	next_cr++;
+}
+
+/*!
+ * This is a little trick to save some space. Write these registers
+ * sequentially to save us a little bit of data space.
+ *
+ * @param value
+ *
+ * @return void
+ */
+void write_next_gr_reg(unsigned char value)
+{
+	write_vga_reg(g_mmio, GR_PORT, next_gr, value);
+	next_gr++;
+}
+
+/*!
+ * This function programs the Timing registers and clock registers and
+ * other control registers for PIPE.
+ *
+ * @param emgd_crtc
+ * @param timings
+ *
+ * @return void
+ */
+void kms_program_pipe_vga(emgd_crtc_t *emgd_crtc,
+	igd_timing_info_t *timings)
+{
+	struct drm_device  *dev = NULL;
+	igd_context_t      *context = NULL;
+	igd_display_pipe_t *pipe = NULL;
+	unsigned char *mmio, i;
+	unsigned char *colors=0;
+	unsigned char palette_hack=0;
+	unsigned char *color_bits = 0;
+	int mode_index;
+	unsigned char msr_temp;
+
+	/* This is a mapping from the HAL mode number to the type of Palette
+	 * being programmed for this mode. */
+	char palette_type[] = {
+	/* 9=Don't care.
+	 *  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f */
+		1, 1, 1, 1, 1, 1, 1, 2,	9, 9, 9, 9, 9, 1, 1, 9,
+		9, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 4 };
+
+	EMGD_TRACE_ENTER;
+
+	pipe = emgd_crtc->igd_pipe;
+	dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+	mmio = (unsigned char *)context->device_context.virt_mmadr;
+	g_mmio = mmio;
+	mode_index = timings->mode_number;
+
+	EMGD_DEBUG("IGD Mode#:0x%x", mode_index);
+
+	/* Disable Group 0 Protection */
+	write_vga_reg(mmio, CR_PORT, 0x11, 0x00);
+
+	/*
+	 * Note: for monochrome modes this will cause the IO port to change
+	 * for the CRTC and the Status regs.
+	 */
+	 msr_temp = (*vga_mode_data_ptr)[mode_index].misc_reg;
+
+#ifdef CONFIG_GN4
+	/*
+	 * According to Chrontel the VGA By-pass requires the HSYNC and VSYNC to be
+	 * of positive polarity.  In the MSR - Miscellaneous Output register
+	 * Bit 7 is CRT VSYNC polarity (0 = Positive, 1 = Negative)
+	 * Bit 6 is CRT HSYNC polarity (0 = Positive, 1 = Negative)
+	 */
+	{
+		pt = get_port_type(emgd_crtc->crtc_id);
+		if (pt == IGD_PORT_DIGITAL) {
+			msr_temp &= (~(BIT(7)|BIT(6)));
+		}
+	}
+#endif
+	EMGD_WRITE8(msr_temp, EMGD_MMIO(mmio) + 0x3c2);
+
+	if((*vga_mode_data_ptr)[mode_index].misc_reg & 1) {
+		vga_port_offset = 0x20;
+	} else {
+		vga_port_offset = 0;
+	}
+
+	/* Sequencer registers */
+	/*
+	 * Note: Most specs say 0 in SR00 scratch bits but in practice seems
+	 * that everyone uses 3.
+	 */
+	write_vga_reg(mmio, SR_PORT, 0x00, 0x03);
+	/* SR01 is on/off and done in program plane */
+	for (i=2; i<=4; i++) {
+		write_vga_reg(mmio, SR_PORT, i,
+			/* The SR Regs in the table are from SR01-SR04, there is
+			 * no SR00 in the table, so -1. */
+			(*vga_mode_data_ptr)[mode_index].sr_regs[i-1]);
+	}
+
+	/* Graphics control registers 0x0-0x8,0x10 */
+	next_gr = 0;
+	for(i=0; i<=0x8; i++) {
+		write_next_gr_reg((*vga_mode_data_ptr)[mode_index].gr_regs[i]);
+	}
+	/*
+	 * GR10 is a non-standard register that controls the mapping of
+	 * 0xa000 to MMIO or GTT memory.
+	 */
+	next_gr = 0x10;
+	write_next_gr_reg(0x0);
+
+	next_ar = 0;
+	for(i=0; i<=0x13; i++) {
+		write_next_ar_reg((*vga_mode_data_ptr)[mode_index].ar_regs[i]);
+	}
+	/* Spec says 0x8 for text modes, not done in practice */
+	write_next_ar_reg(0x00);
+
+	/* Ensure the Pixel Data Mask Register does not mask the pixel data */
+	EMGD_WRITE8(0xFF, EMGD_MMIO(mmio) + 0x3c6);
+
+	/* set DAC data value */
+	EMGD_WRITE8(0, EMGD_MMIO(mmio) + 0x3c8);
+
+	/* Load RAMDAC*/
+	switch(palette_type[mode_index]){
+	case 0:
+		color_bits = p64_color_bits;
+		colors = normal_colors;
+		palette_hack = 0;
+		break;
+	case 1:
+		color_bits = p16_color_bits;
+		colors = normal_colors;
+		palette_hack = 1;
+		break;
+	case 2:
+		color_bits = mono_color_bits;
+		colors = mono_colors;
+		palette_hack = 0;
+		break;
+	default:
+		break;
+	}
+	/* Program the Palette based on the mode. */
+	if (!vga_disable_default_palette_load) {
+		if (color_bits) {
+			set_palette_vga(mmio, 64, color_bits, colors, palette_hack);
+			set_3f_palette(mmio, 192);
+		} else {
+			set_256_palette(mmio);
+		}
+	}
+
+	/* Timings */
+	next_cr = 0;
+	for(i=0; i<=0x18; i++) {
+		write_next_cr_reg((*vga_mode_data_ptr)[mode_index].crtc_regs[i]);
+	}
+
+	return;
+}
+
+
+/*!
+ * This function programs the Timing registers and clock registers and
+ * other control registers for PIPE.
+ *
+ * @param display
+ * @param timings
+ *
+ * @return void
+ */
+void program_pipe_vga(igd_display_context_t *display,
+	igd_timing_info_t *timings)
+{
+	unsigned char *mmio, i;
+	unsigned char *colors=0;
+	unsigned char palette_hack=0;
+	unsigned char *color_bits = 0;
+	int mode_index;
+	unsigned char msr_temp;
+
+	/* This is a mapping from the HAL mode number to the type of Palette
+	 * being programmed for this mode. */
+	char palette_type[] = {
+	/* 9=Don't care.
+	 *  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f */
+		1, 1, 1, 1, 1, 1, 1, 2,	9, 9, 9, 9, 9, 1, 1, 9,
+		9, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 4 };
+
+	EMGD_DEBUG("Enter program_pipe_vga");
+
+	mmio = (unsigned char *)MMIO(display);
+	g_mmio = mmio;
+	mode_index = timings->mode_number;
+
+	EMGD_DEBUG("IGD Mode#:0x%x", mode_index);
+
+	/* Disable Group 0 Protection */
+	write_vga_reg(mmio, CR_PORT, 0x11, 0x00);
+
+	/*
+	 * Note: for monochrome modes this will cause the IO port to change
+	 * for the CRTC and the Status regs.
+	 */
+	 msr_temp = (*vga_mode_data_ptr)[mode_index].misc_reg;
+
+#ifdef CONFIG_GN4
+	/*
+	 * According to Chrontel the VGA By-pass requires the HSYNC and VSYNC to be
+	 * of positive polarity.  In the MSR - Miscellaneous Output register
+	 * Bit 7 is CRT VSYNC polarity (0 = Positive, 1 = Negative)
+	 * Bit 6 is CRT HSYNC polarity (0 = Positive, 1 = Negative)
+	 */
+	{
+		igd_display_port_t *port;
+		port = PORT_OWNER(display);
+		if (port->port_type == IGD_PORT_DIGITAL) {
+			msr_temp &= (~(BIT(7)|BIT(6)));
+		}
+	}
+#endif
+	EMGD_WRITE8(msr_temp, EMGD_MMIO(mmio) + 0x3c2);
+
+	if((*vga_mode_data_ptr)[mode_index].misc_reg & 1) {
+		vga_port_offset = 0x20;
+	} else {
+		vga_port_offset = 0;
+	}
+
+	/* Sequencer registers */
+	/*
+	 * Note: Most specs say 0 in SR00 scratch bits but in practice seems
+	 * that everyone uses 3.
+	 */
+	write_vga_reg(mmio, SR_PORT, 0x00, 0x03);
+	/* SR01 is on/off and done in program plane */
+	for (i=2; i<=4; i++) {
+		write_vga_reg(mmio, SR_PORT, i,
+			/* The SR Regs in the table are from SR01-SR04, there is
+			 * no SR00 in the table, so -1. */
+			(*vga_mode_data_ptr)[mode_index].sr_regs[i-1]);
+	}
+
+	/* Graphics control registers 0x0-0x8,0x10 */
+	next_gr = 0;
+	for(i=0; i<=0x8; i++) {
+		write_next_gr_reg((*vga_mode_data_ptr)[mode_index].gr_regs[i]);
+	}
+	/*
+	 * GR10 is a non-standard register that controls the mapping of
+	 * 0xa000 to MMIO or GTT memory.
+	 */
+	next_gr = 0x10;
+	write_next_gr_reg(0x0);
+
+	next_ar = 0;
+	for(i=0; i<=0x13; i++) {
+		write_next_ar_reg((*vga_mode_data_ptr)[mode_index].ar_regs[i]);
+	}
+	/* Spec says 0x8 for text modes, not done in practice */
+	write_next_ar_reg(0x00);
+
+	/* Ensure the Pixel Data Mask Register does not mask the pixel data */
+	EMGD_WRITE8(0xFF, EMGD_MMIO(mmio) + 0x3c6);
+
+	/* set DAC data value */
+	EMGD_WRITE8(0, EMGD_MMIO(mmio) + 0x3c8);
+
+	/* Load RAMDAC*/
+	switch(palette_type[mode_index]){
+	case 0:
+		color_bits = p64_color_bits;
+		colors = normal_colors;
+		palette_hack = 0;
+		break;
+	case 1:
+		color_bits = p16_color_bits;
+		colors = normal_colors;
+		palette_hack = 1;
+		break;
+	case 2:
+		color_bits = mono_color_bits;
+		colors = mono_colors;
+		palette_hack = 0;
+		break;
+	default:
+		break;
+	}
+	/* Program the Palette based on the mode. */
+	if (!vga_disable_default_palette_load) {
+		if (color_bits) {
+			set_palette_vga(mmio, 64, color_bits, colors, palette_hack);
+			set_3f_palette(mmio, 192);
+		} else {
+			set_256_palette(mmio);
+		}
+	}
+
+	/* Timings */
+	next_cr = 0;
+	for(i=0; i<=0x18; i++) {
+		write_next_cr_reg((*vga_mode_data_ptr)[mode_index].crtc_regs[i]);
+	}
+
+	return;
+}
+
+/*
+ * The HAL mode numbers match up to VGA modes in this way:
+ *   VGA Mode : HAL Mode
+ *      00         00
+ *      01         01
+ *      02         02
+ *      03         03
+ *      04         04
+ *      05         05
+ *      06         06
+ *      07         07
+ *      0d         0d
+ *      0e         0e
+ *      0f         11
+ *      10         12
+ *      00*        13
+ *      01*        14
+ *      02*        15
+ *      03*        16
+ *      00+        17
+ *      01+        17
+ *      02+        18
+ *      03+        18
+ *      07+        19
+ *      11         1A
+ *      12         1B
+ *      13         1C
+ */
+
+/* This can not be a static, since the vBIOS will use this as a global */
+vga_mode_data_t VB_CODE_SEG vga_mode_data[] = {
+	/*============================================================================*/
+	/* Modes 00h (Text 40 x 25 Colors 16 gray Font 8 x 8) - Table Entry 00h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x28,0x18,0x08,	/* Text Columns Rows Font */
+		0x0800,			/* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x09,0x03,0x00,0x02},
+
+		/* Miscellaneous output register value. */
+		0x63,
+
+		/* CRT Controller register values. */
+		{0x2D,0x27,0x28,0x90,0x2B,0xA0,0xBF,0x1F,
+		 0x00,0xC7,0x06,0x07,0x00,0x00,0x00,0x00,
+		 0x9C,0x8E,0x8F,0x14,0x1F,0x96,0xB9,0xA3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+		 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+		 0x08,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 01h (Text 40 x 25 Colors 16 gray Font 8 x 8) - Table Entry 01h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x28,0x18,0x08,	/* Text Columns Rows Font */
+		0x0800,			/* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x09,0x03,0x00,0x02},
+
+		/* Miscellaneous output register value. */
+		0x63,
+
+		/* CRT Controller register values. */
+		{0x2D,0x27,0x28,0x90,0x2B,0xA0,0xBF,0x1F,
+		 0x00,0xC7,0x06,0x07,0x00,0x00,0x00,0x00,
+		 0x9C,0x8E,0x8F,0x14,0x1F,0x96,0xB9,0xA3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+		 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+		 0x08,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 02h (Text 80 x 25 Colors 16 gray Font 8 x 8) - Table Entry 02h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x18,0x08,	/* Text Columns Rows Font */
+		0x1000,			/* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x01,0x03,0x00,0x02},
+
+		/* Miscellaneous output register value. */
+		0x63,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+		 0x00,0xC7,0x06,0x07,0x00,0x00,0x00,0x00,
+		 0x9C,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xA3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+		 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+		 0x08,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 03h (Text 80 x 25 Colors 16 Font 8 x 8) - Table Entry 03h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x18,0x08,	/* Text Columns Rows Font */
+		0x1000,			/* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x01,0x03,0x00,0x02},
+
+		/* Miscellaneous output register value. */
+		0x63,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+		 0x00,0xC7,0x06,0x07,0x00,0x00,0x00,0x00,
+		 0x9C,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xA3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+		 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+		 0x08,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 04h (Graphics 320 x 200 Colors 4 Font 8 x 8) - Table Entry 04h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x28,0x18,0x08,	/* Text Columns Rows Font */
+		0x4000,	        /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x09,0x03,0x00,0x02},
+
+		/* Miscellaneous output register value. */
+		0x63,
+
+		/* CRT Controller register values. */
+		{0x2D,0x27,0x28,0x90,0x2B,0x80,0xBF,0x1F,
+		 0x00,0xC1,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x9C,0x8E,0x8F,0x14,0x00,0x96,0xB9,0xA2,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
+		 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+		 0x01,0x00,0x03,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x30,0x0F,0x00,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 05h (Graphics 320 x 200 Colors 4 gray Font 8 x 8) - Table 05h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x28,0x18,0x08,	/* Text Columns Rows Font */
+		0x4000,	        /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x09,0x03,0x00,0x02},
+
+		/* Miscellaneous output register value. */
+		0x63,
+
+		/* CRT Controller register values. */
+		{0x2D,0x27,0x28,0x90,0x2B,0x80,0xBF,0x1F,
+		 0x00,0xC1,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x9C,0x8E,0x8F,0x14,0x00,0x96,0xB9,0xA2,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
+		 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+		 0x01,0x00,0x03,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x30,0x0F,0x00,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 06h (Graphics 640 x 200 Colors 2 Font 8 x 8) - Table Entry 06h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x18,0x08,	/* Text Columns Rows Font */
+		0x4000,	        /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x01,0x01,0x00,0x06},
+
+		/* Miscellaneous output register value. */
+		0x63,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,
+		 0x00,0xC1,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x9C,0x8E,0x8F,0x28,0x00,0x96,0xB9,0xC2,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+		 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+		 0x01,0x00,0x01,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x00,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 07h (Text 80 x 25 Colors 2 Font 9 x 14) - Table Entry 07h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x18,0x0E,	/* Text Columns Rows Font */
+		0x1000,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x00,0x03,0x00,0x03},
+
+		/* Miscellaneous output register value. */
+		0xA6,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+		 0x00,0x4D,0x0B,0x0C,0x00,0x00,0x00,0x00,
+		 0x83,0x85,0x5D,0x28,0x0D,0x63,0xBA,0xA3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+		 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+		 0x0E,0x00,0x0F,0x08},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x10,0x0A,0x00,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Blank Entry - Table Entry 08h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x18,0x10,	/* Text Columns Rows Font */
+		0x7D00,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x21,0x0F,0x00,0x06},
+
+		/* Miscellaneous output register value. */
+		0x63,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+		 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x9C,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xE3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+		 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+		 0x01,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Blank Entry - Table Entry 09h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x00,0x00,0x00,	/* Text Columns Rows Font */
+		0x0000,         /* Page size */
+
+		/* Sequencer register values. */
+		{0x00,0x00,0x00,0x00},
+
+		/* Miscellaneous output register value. */
+		0x00,
+
+		/* CRT Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x00},
+
+		/* Attribute Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x00,0x00,0x00,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x00},
+	},
+
+	/*============================================================================*/
+	/* Blank Entry - Table Entry 0Ah */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x28,0x18,0x08,	/* Text Columns Rows Font */
+		0x4000,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x00,0x00,0x00,0x03},
+
+		/* Miscellaneous output register value. */
+		0x23,
+
+		/* CRT Controller register values. */
+		{0x37,0x27,0x2D,0x37,0x31,0x15,0x04,0x11,
+		 0x00,0x47,0x06,0x07,0x00,0x00,0x00,0x00,
+		 0xE1,0x24,0xC7,0x14,0x08,0xE0,0xF0,0xA3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+		 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+		 0x08,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Blank Entry - Table Entry 0Bh */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x00,0x00,	/* Text Columns Rows Font */
+		0x0000,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x29,0x0F,0x00,0x06},
+
+		/* Miscellaneous output register value. */
+		0x62,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+		 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x9C,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xE3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,
+		 0x01,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x0F,0x00,0x00,0x08,0x05,0x0F,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Blank Entry - Table Entry 0Ch */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x00,0x00,	/* Text Columns Rows Font */
+		0x0000,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x29,0x0F,0x00,0x06},
+
+		/* Miscellaneous output register value. */
+		0x63,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+		 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x9C,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xE3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,
+		 0x01,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x0F,0x00,0x00,0x08,0x05,0x0F,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 0Dh (Graphics 320 x 200 Colors 16 Font 8 x 8) - Table Entry 0Dh */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x28,0x18,0x08,	/* Text Columns Rows Font */
+		0x2000,         /* Page size */
+
+		/* Sequencer register values. */
+		{0x09,0x0F,0x00,0x06},
+
+		/* Miscellaneous output register value. */
+		0x63,
+
+		/* CRT Controller register values. */
+		{0x2D,0x27,0x28,0x90,0x2B,0x80,0xBF,0x1F,
+		 0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x9C,0x8E,0x8F,0x14,0x00,0x96,0xB9,0xE3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+		 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+		 0x01,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 0Eh (Graphics 640 x 200 Colors 16 Font 8 x 8) - Table Entry 0Eh */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x18,0x08,	/* Text Columns Rows Font */
+		0x4000,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x01,0x0F,0x00,0x06},
+
+		/* Miscellaneous output register value. */
+		0x63,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,
+		 0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x9C,0x8E,0x8F,0x28,0x00,0x96,0xB9,0xE3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+		 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+		 0x01,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Blank Entry - Table Entry 0Fh */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x18,0x0E,	/* Text Columns Rows Font */
+		0x8000,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x05,0x0F,0x00,0x00},
+
+		/* Miscellaneous output register value. */
+		0xA2,
+
+		/* CRT Controller register values. */
+		{0x60,0x4F,0x56,0x1A,0x50,0xE0,0x70,0x1F,
+		 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x5E,0x2E,0x5D,0x14,0x00,0x5E,0x6E,0x8B,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00,
+		 0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,
+		 0x0B,0x00,0x05,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x10,0x07,0x0F,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Blank Entry - Table Entry 10h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x18,0x0E,	/* Text Columns Rows Font */
+		0x8000,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x05,0x0F,0x00,0x00},
+
+		/* Miscellaneous output register value. */
+		0xA7,
+
+		/* CRT Controller register values. */
+		{0x5B,0x4F,0x53,0x17,0x50,0xBA,0x6C,0x1F,
+		 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x5E,0x2B,0x5D,0x14,0x0F,0x5F,0x0A,0x8B,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x00,0x00,0x04,0x07,0x00,0x00,
+		 0x00,0x01,0x00,0x00,0x04,0x07,0x00,0x00,
+		 0x01,0x00,0x05,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x10,0x07,0x0F,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 0Fh; (Graphics 640 x 350 Colors 2 Font 8 x 14) - Table Entry 11h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x18,0x0E,	/* Text Columns Rows Font */
+		0x8000,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x01,0x0F,0x00,0x06},
+
+		/* Miscellaneous output register value. */
+		0xA2,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,
+		 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x83,0x85,0x5D,0x28,0x0F,0x63,0xBA,0xE3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00,
+		 0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,
+		 0x0B,0x00,0x05,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 10h; (Graphics 640 x 350 Colors 16 Font 8 x 14) - Table Entry 12h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x18,0x0E,	/* Text Columns Rows Font */
+		0x8000,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x01,0x0F,0x00,0x06},
+
+		/* Miscellaneous output register value. */
+		0xA3,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,
+		 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x83,0x85,0x5D,0x28,0x0F,0x63,0xBA,0xE3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+		 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+		 0x01,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 00h; (Text 40 x 25 Colors 16 gray Font 8 x 14) - Table Entry 13h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x28,0x18,0x0E,	/* Text Columns Rows Font */
+		0x0800,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x09,0x03,0x00,0x02},
+
+		/* Miscellaneous output register value. */
+		0xA3,
+
+		/* CRT Controller register values. */
+		{0x2D,0x27,0x28,0x90,0x2B,0xA0,0xBF,0x1F,
+		 0x00,0x4D,0x0B,0x0C,0x00,0x00,0x00,0x00,
+		 0x83,0x85,0x5D,0x14,0x1F,0x63,0xBA,0xA3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+		 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+		 0x08,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 01h; (Text 40 x 25 Colors 16 Font 8 x 14) - Table Entry 14h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x28,0x18,0x0E,	/* Text Columns Rows Font */
+		0x0800,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x09,0x03,0x00,0x02},
+
+		/* Miscellaneous output register value. */
+		0xA3,
+
+		/* CRT Controller register values. */
+		{0x2D,0x27,0x28,0x90,0x2B,0xA0,0xBF,0x1F,
+		 0x00,0x4D,0x0B,0x0C,0x00,0x00,0x00,0x00,
+		 0x83,0x85,0x5D,0x14,0x1F,0x63,0xBA,0xA3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+		 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+		 0x08,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+// ; Modes 02h; (Text 80 x 25 Colors 16 gray Font 8 x 14) - Table Entry 15h //
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x18,0x0E,	/* Text Columns Rows Font */
+		0x1000,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x01,0x03,0x00,0x02},
+
+		/* Miscellaneous output register value. */
+		0xA3,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+		 0x00,0x4D,0x0B,0x0C,0x00,0x00,0x00,0x00,
+		 0x83,0x85,0x5D,0x28,0x1F,0x63,0xBA,0xA3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+		 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+		 0x08,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 03h; (Text 80 x 25 Colors 16 Font 8 x 14) - Table Entry 16h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x18,0x0E, /* Text Columns Rows Font */
+		0x1000,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x01,0x03,0x00,0x02},
+
+		/* Miscellaneous output register value. */
+		0xA3,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+		 0x00,0x4D,0x0B,0x0C,0x00,0x00,0x00,0x00,
+		 0x83,0x85,0x5D,0x28,0x1F,0x63,0xBA,0xA3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+		 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+		 0x08,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 00h+ ; 01h+ (Text 40 x 25 Colors 16 Font 9 x 16) - Table 17h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x28,0x18,0x10, /* Text Columns Rows Font */
+		0x0800,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x08,0x03,0x00,0x02},
+
+		/* Miscellaneous output register value. */
+		0x67,
+
+		/* CRT Controller register values. */
+		{0x2D,0x27,0x28,0x90,0x2B,0xA0,0xBF,0x1F,
+		 0x00,0x4F,0x0D,0x0E,0x00,0x00,0x00,0x00,
+		 0x9C,0x8E,0x8F,0x14,0x1F,0x96,0xB9,0xA3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+		 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+		 0x0C,0x00,0x0F,0x08},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 02h+ ; 03h+ (Text 80 x 25 Colors 16 Font 9 x 16) - Table 18h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x18,0x10,	/* Text Columns Rows Font */
+		0x1000,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x00,0x03,0x00,0x02},
+
+		/* Miscellaneous output register value. */
+		0x67,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+		 0x00,0x4F,0x0D,0x0E,0x00,0x00,0x00,0x00,
+		 0x9C,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xA3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+		 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+		 0x0C,0x00,0x0F,0x08},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 07h+ (Text 80 x 25 Colors 2 Font 9 x 16) - Table Entry 19h */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x18,0x10,	/* Text Columns Rows Font */
+		0x1000,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x00,0x03,0x00,0x02},
+
+		/* Miscellaneous output register value. */
+		0x66,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,
+		 0x00,0x4F,0x0D,0x0E,0x00,0x00,0x00,0x00,
+		 0x9C,0x8E,0x8F,0x28,0x0F,0x96,0xB9,0xA3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+		 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+		 0x0E,0x00,0x0F,0x08},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x10,0x0A,0x00,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 11h (Graphics 640 x 480 Colors 2 Font 8 x 16) - Table Entry 1Ah */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x1D,0x10,	/* Text Columns Rows Font */
+		0xA000,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x01,0x0F,0x00,0x06},
+
+		/* Miscellaneous output register value. */
+		0xE3,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E,
+		 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0xEA,0x8C,0xDF,0x28,0x00,0xE7,0x04,0xC3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+		 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+		 0x01,0x00,0x01,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 12h (Graphics 640 x 480 Colors 16 Font 8 x 16) - Table Entry 1Bh */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x50,0x1D,0x10,	/* Text Columns Rows Font */
+		0xA000,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x01,0x0F,0x00,0x06},
+
+		/* Miscellaneous output register value. */
+		0xE3,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E,
+		 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0xEA,0x8C,0xDF,0x28,0x00,0xE7,0x04,0xE3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+		 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+		 0x01,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F,
+		 0xFF},
+	},
+
+	/*============================================================================*/
+	/* Modes 13h (Graphics 320 x 200 Colors 256 Font 8 x 8) - Table Entry 1Ch */
+	/*----------------------------------------------------------------------------*/
+	{
+		0x28,0x18,0x08, /* Text Columns Rows Font */
+		0x2000,         /* Page size */
+
+		/* Sequencer register values, SR01-SR04. */
+		{0x01,0x0F,0x00,0x0E},
+
+		/* Miscellaneous output register value. */
+		0x63,
+
+		/* CRT Controller register values. */
+		{0x5F,0x4F,0x50,0x82,0x54,0x80,0xBF,0x1F,
+		 0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
+		 0x9C,0x8E,0x8F,0x28,0x40,0x96,0xB9,0xA3,
+		 0xFF},
+
+		/* Attribute Controller register values. */
+		{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+		 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
+		 0x41,0x00,0x0F,0x00},
+
+		/* Graphics Controller register values. */
+		{0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0F,
+		 0xFF}
+	},
+};
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/plb/clocks_plb.c b/drivers/gpu/drm/emgd/emgd/display/mode/plb/clocks_plb.c
new file mode 100644
index 0000000..f39e9d2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/plb/clocks_plb.c
@@ -0,0 +1,711 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: clocks_plb.c
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+#include <io.h>
+
+#include <igd_mode.h>
+#include <igd_init.h>
+
+#include <context.h>
+#include <intelpci.h>
+#include <dsp.h>
+#include <utils.h>
+#include <mode.h>
+#include <pi.h>
+#include <sched.h>
+
+#include "drm_emgd_private.h"
+#include <plb/regs.h>
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/*===========================================================================
+; File Global Data
+;--------------------------------------------------------------------------*/
+typedef struct _fixed_clock {
+	unsigned long dclk;
+	unsigned long n;
+	unsigned long m1;
+	unsigned long m2;
+	unsigned long p;
+}fixed_clock_t;
+
+static fixed_clock_t fixed_clock_table[] =  {
+	/* Clock    N    M1    M2  Post Div */
+    { 43163, 0x03, 0x12, 0x06, 0x84},  /* 43.163 GTF for 640x480 @ 100Hz */
+    { 81624, 0x03, 0x18, 0x04, 0x82},  /* 81.624MHz */
+	{0xffffffff, 0x00, 0x00, 0x00, 0x00}
+};
+
+/*!
+ * This function translates from the calculated M value to the M1, M2
+ * register values.
+ *
+ * @param m
+ * @param *m1
+ * @param *m2
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int calculate_m1_m2(unsigned long m,
+	unsigned long *m1,
+	unsigned long *m2)
+{
+	unsigned long current_m1, current_m2;
+
+	EMGD_DEBUG("Enter calculate_m1_m2 %d", 1);
+
+	/* ori was in steps of 2*/
+	for(current_m1 = (10+2); current_m1 <= (20+2); current_m1 += 1) {
+		for(current_m2 = (5+2); current_m2 <= (9+2); current_m2++)  {
+			if((current_m1 * 5 + current_m2) == m) {
+				*m1 = current_m1 - 2;
+				*m2 = current_m2 - 2;
+				return 0;
+			}
+
+		}
+	}
+
+	EMGD_DEBUG("M1, M2 not found for M == %ld", m);
+	return 1;
+}
+
+#define MAX_M 120 //216
+#define MIN_M 70 //96
+
+#define MAX_N 8 //16
+#define MIN_N 3
+
+#define MAX_P 80 //126
+#define MIN_P 5 //2
+
+#define LVDS_MAX_P 98
+#define LVDS_MIN_P 7
+
+#define FIX_P2_LO 5 //126
+#define FIX_P2_HI 10 //2
+
+#define MAX_P1 8 //126
+#define MIN_P1 1 //2
+
+#define REF_FREQ 96000 //48000
+#define MAX_VCO 2800000 //1400000
+#define MAX_FP 200000
+/* For LVDS port */
+#define LVDS_FIX_P2_LO 7
+#define LVDS_FIX_P2_HI 14
+
+/*!
+ *
+ * @param dclk
+ * @param ref_freq
+ * @param m1
+ * @param m2
+ * @param n
+ * @param p
+ * @param min_vco
+ * @param target_error
+ * @param port_type
+ * @param dual_channel
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int calculate_clock(unsigned long dclk,
+	unsigned long ref_freq,
+	unsigned long *m1,
+	unsigned long *m2,
+	unsigned long *n,
+	unsigned long *p,
+	unsigned long min_vco,
+	unsigned long target_error,
+	unsigned long port_type,
+	unsigned long dual_channel)
+
+{
+	unsigned long p1;
+	unsigned long p2;
+	/* Parameters */
+    unsigned long freqmult_p2;
+
+	/* Intermidiate variables */
+	unsigned long  pdiv;
+	unsigned long  target_vco, actual_freq, actual_vco;
+	long freq_error, min_error;
+
+	unsigned long current_m, current_n, current_p1;
+	unsigned long best_m = 0;
+	unsigned long best_n = 0;
+	unsigned long best_p1 = 0;
+
+
+	EMGD_DEBUG("Enter calculate_clock");
+
+	min_error = 100000;
+
+	if (dclk > MAX_FP) {
+		freqmult_p2 = FIX_P2_LO;
+	} else {
+		freqmult_p2 = FIX_P2_HI;
+	}
+
+	/* For LVDS port */
+	if(port_type==IGD_PORT_LVDS){
+		/* Test if we are dual channel */
+		if(dual_channel){
+			freqmult_p2=LVDS_FIX_P2_LO;
+		} else{
+			freqmult_p2=LVDS_FIX_P2_HI;
+		}
+
+	}
+
+	for(current_m = MIN_M; current_m <= MAX_M; current_m++) {
+		for(current_n = MIN_N; current_n < MAX_N; current_n++) {
+			for(current_p1 = MIN_P1; current_p1 <= MAX_P1; current_p1++) {
+
+				pdiv = freqmult_p2 * current_p1;
+				target_vco = dclk * pdiv;
+
+				if ((target_vco <= MAX_VCO) && (target_vco >= min_vco)) {
+					actual_freq = (ref_freq * current_m) /
+						(current_n * pdiv);
+					actual_vco = actual_freq * pdiv;
+					freq_error = 10000 - (dclk * 10000 / actual_freq);
+
+					if (freq_error < 0) {
+						freq_error = -freq_error;
+					}
+					if (freq_error < min_error)  {
+						best_n = current_n;
+						best_m = current_m;
+						best_p1 = current_p1;
+						min_error = freq_error;
+					}
+					if (min_error == 0) {
+						break;
+					}
+				}
+			}
+			if (min_error == 0) {
+				break;
+			}
+		}
+		if (min_error == 0) {
+			break;
+		}
+	}
+	/*
+	 * No clock found that meets error requirement
+	 */
+	if (min_error > (long)target_error) {
+		return 1;
+	}
+
+
+	/* Translate M,N,P to m1,m2,n,p register values */
+	*n = best_n - 2;
+	if(calculate_m1_m2(best_m, m1, m2)) {
+		/* No M1, M2 match for M */
+		return 1;
+	}
+
+	p1 = (1 << (best_p1-1));
+	if((freqmult_p2-5)) {
+		p2 = 0x0;
+	}
+	else {
+		p2 = 0x1;
+	}
+	/* Set p2 for LVDS */
+	if(port_type==IGD_PORT_LVDS){
+		if(dual_channel){
+			p2=0x1;
+		}else{
+			p2=0x0;
+		}
+
+	}
+	*p = (  p1 | (p2<<8) );
+
+	return 0;
+}
+
+#define MIN_VCO_PASS1 2000000 //1000000
+#define MIN_VCO_PASS2 1400000 //930000
+
+/*!
+ *
+ * @param dclk
+ * @param ref_freq
+ * @param m1
+ * @param m2
+ * @param n
+ * @param p
+ * @param target_error
+ * @param port_type
+ * @param dual_channel
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int get_clock(unsigned long dclk,
+	unsigned long ref_freq,
+	unsigned long *m1,
+	unsigned long *m2,
+	unsigned long *n,
+	unsigned long *p,
+	unsigned long target_error,
+	unsigned long port_type,
+	unsigned long dual_channel)
+{
+	fixed_clock_t *fixed = fixed_clock_table;
+
+	EMGD_DEBUG("Enter get_clock");
+
+	/*
+	 * First check for a fixed clock from the table. These are ones that
+	 * can't be calculated correctly.
+	 */
+	while(fixed->dclk != 0xffffffff) {
+		if(fixed->dclk == dclk) {
+			EMGD_DEBUG("Using Fixed Clock From table for clock %ld", dclk);
+			*m1 = fixed->m1;
+			*m2 = fixed->m2;
+			*n = fixed->n;
+			*p = fixed->p;
+			return 0;
+		}
+		fixed++;
+	}
+
+
+	/*
+	 * No fixed clock found so calculate one.
+	 */
+	EMGD_DEBUG("Calculating dynamic clock for clock %ld", dclk);
+
+	/*
+	 * First pass try to find a clock with min_vco at 1000000.
+	 * If a clock doesn't come out then try 930000.
+	 */
+	if(calculate_clock(dclk, ref_freq, m1, m2, n, p, MIN_VCO_PASS1,
+		   target_error,port_type,dual_channel)) {
+		if(calculate_clock(dclk, ref_freq, m1, m2, n, p, MIN_VCO_PASS2,
+			   target_error,port_type,dual_channel)) {
+			/* No usable clock */
+			EMGD_ERROR("Could not calculate clock %ld, returning default.",
+				dclk);
+			*m1 = 0x14;
+			*m2 = 0xc;
+			*n = 0x3;
+			*p = 0x82;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+#define TARGET_ERROR 46
+
+/*!
+ *
+ * @param emgd_crtc
+ * @param clock
+ * @param dclk
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int kms_program_clock_plb(emgd_crtc_t *emgd_crtc,
+	igd_clock_t *clock,
+	unsigned long dclk)
+{
+	unsigned long m1, m2, n, p;
+	unsigned long control;
+	unsigned long ref_freq;
+	int ret;
+	unsigned long port_mult, vga_mult;
+	unsigned long dual_channel = 0;
+	unsigned long index;
+	unsigned long pt;
+	struct drm_device  *dev          = NULL;
+	igd_display_pipe_t *pipe         = NULL;
+	igd_context_t      *context      = NULL;
+	igd_display_port_t *port         = NULL;
+	struct drm_encoder *encoder      = NULL;
+	emgd_encoder_t     *emgd_encoder = NULL;
+
+	EMGD_DEBUG("Enter program_clock");
+
+	pipe = emgd_crtc->igd_pipe;
+	dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (((struct drm_crtc *)(&emgd_crtc->base)) == encoder->crtc) {
+			emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+			port = emgd_encoder->igd_port;
+			pt = port->port_type;
+			break;
+		}
+	}
+	if (!port) {
+		EMGD_ERROR_EXIT("No port");
+		return -1;
+	}
+
+	if (dclk > 100000) {        /*	100-200 MHz	*/
+
+		port_mult = 1;
+	}
+	else if (dclk > 50000) {    /*	50-100 Mhz	*/
+
+		port_mult = 2;
+	}
+	else {                      /*	25-50 Mhz	*/
+
+		port_mult = 4;
+	}
+
+	/*
+	 * Clock Multiplier : sDVO ports on all plb chipsets
+	 */
+	if (pt == IGD_PORT_DIGITAL) {
+
+		dclk *= port_mult;
+	}
+
+	vga_mult = EMGD_READ32(context->device_context.virt_mmadr + clock->dpll_control) & 0x3;
+
+	/* For Int-LVDS need to find out if its dual channel and pass
+	 * that info into caluculating for p2. Apperently halving
+	 * of dot-clock is also required by Ch7017 when operating in
+	 * dual channel
+	 */
+	if (pt == IGD_PORT_LVDS) {
+		/* Find PD_ATTR_ID_2_CHANNEL_PANEL attr value*/
+		pi_pd_find_attr_and_value(port,
+				PD_ATTR_ID_2_CHANNEL_PANEL,
+				0/*no PD_FLAG for 2_channel*/,
+				NULL,
+				&dual_channel);
+	}
+
+	/* For external clock sources always use ref_clock == dclk */
+	if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+		ref_freq = dclk;
+	} else {
+		ref_freq = 96000;
+	}
+	/* LVDS reference clock can be 96 or 100 MHz. However there
+	 * are no mention in the specification to specify which register
+	 * to select/set this.
+	 */
+
+	/* When the clock source is provided externally by the port driver,
+	 * the allowed error range is 0. */
+	if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+		ret = get_clock(dclk, ref_freq, &m1, &m2, &n, &p, 0
+				,pt,dual_channel);
+	} else {
+		ret = get_clock(dclk, ref_freq, &m1, &m2, &n, &p, TARGET_ERROR
+				,pt,dual_channel);
+	}
+
+	if(ret) {
+		EMGD_ERROR("Clock %ld could not be programmed", dclk);
+		return ret;
+	}
+
+	/* Disable DPLL, Write an 0x80 into P for saftey */
+	control = 0x10000000 | (0x80<<clock->p_shift) | BIT26 | vga_mult;
+	EMGD_WRITE32(control, context->device_context.virt_mmadr + clock->dpll_control);
+
+	/* Program N, M1,and M2 */
+	EMGD_WRITE32((n<<16) | (m1<<8) | m2, context->device_context.virt_mmadr + clock->mnp);
+
+	/* Enable DPLL, Disable VGAm Mode and sitck in new P values */
+	if(pt == IGD_PORT_LVDS){
+		/* If LVDS set the appropriate bits for mode select */
+		control = (BIT31 | BIT28 | BIT27 )
+			| (p<<clock->p_shift) | vga_mult;
+
+		if(port->attr_list) {
+
+			for(index = 0; index < port->attr_list->num_attrs; index++) {
+
+				/* Set spread spectrum and pulse phase */
+				if(port->attr_list->attr[index].id == PD_ATTR_ID_SSC) {
+
+					/*
+					 * Pulse Phase for Poulsbo only has valid values between
+					 * 3 and 9
+					 */
+					if(port->attr_list->attr[index].value >= 3 &&
+						port->attr_list->attr[index].value <= 9) {
+
+						control |= BIT13 | BIT14;
+						/*
+						 * Set the Pulse Phase to the clock phase specified by
+						 * the user
+						 */
+						control |= (port->attr_list->attr[index].value<<9);
+					}
+					break;
+				}
+			}
+		}
+	} else{
+	/* else DAC/SDVO */
+		control = (BIT31 | BIT28 | BIT26) | (p<<clock->p_shift) | vga_mult;
+	}
+	/*
+	 * Poulsbo has high speed clock on always
+	 */
+	control |= BIT30;
+
+
+
+	/* Set the clock source correctly based on PD settings */
+	if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+		control |= port->clock_bits;
+	} else {
+		control |= port->clock_bits & ~0x00006000;
+	}
+
+	/* sDVO Multiplier bits[7:0] */
+	if (pt == IGD_PORT_DIGITAL) {
+
+		if (port_mult == 2) {
+
+			control |= (1 << 4);
+
+		} else if (port_mult == 4) {
+
+			control |= (3 << 4);
+		}
+	}
+
+	EMGD_WRITE32(control, context->device_context.virt_mmadr + clock->dpll_control);
+
+	/* We must wait for 150 us for the dpll clock to warm up */
+	OS_SLEEP(150);
+	pipe->dclk = dclk;
+
+	return 0;
+}
+
+
+/*!
+ *
+ * @param display
+ * @param clock
+ * @param dclk
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int program_clock_plb(igd_display_context_t *display,
+	igd_clock_t *clock,
+	unsigned long dclk)
+{
+	unsigned long m1, m2, n, p;
+	unsigned long control;
+	unsigned long ref_freq;
+	int ret;
+	igd_display_port_t *port;
+	unsigned long port_mult, vga_mult;
+	unsigned long dual_channel = 0;
+	unsigned long index;
+
+	EMGD_DEBUG("Enter program_clock");
+
+	port=PORT_OWNER(display);
+
+	if (dclk > 100000) {        /*	100-200 MHz	*/
+
+		port_mult = 1;
+	}
+	else if (dclk > 50000) {    /*	50-100 Mhz	*/
+
+		port_mult = 2;
+	}
+	else {                      /*	25-50 Mhz	*/
+
+		port_mult = 4;
+	}
+
+	/*
+	 * Clock Multiplier : sDVO ports on all plb chipsets
+	 */
+	if (port->port_type == IGD_PORT_DIGITAL) {
+
+		dclk *= port_mult;
+	}
+
+	vga_mult = READ_MMIO_REG(display, clock->dpll_control) & 0x3;
+
+	/* For Int-LVDS need to find out if its dual channel and pass
+	 * that info into caluculating for p2. Apperently halving
+	 * of dot-clock is also required by Ch7017 when operating in
+	 * dual channel
+	 */
+	if (port->port_type == IGD_PORT_LVDS) {
+		/* Find PD_ATTR_ID_2_CHANNEL_PANEL attr value*/
+		pi_pd_find_attr_and_value(PORT_OWNER(display),
+				PD_ATTR_ID_2_CHANNEL_PANEL,
+				0/*no PD_FLAG for 2_channel*/,
+				NULL,
+				&dual_channel);
+	}
+
+	/* For external clock sources always use ref_clock == dclk */
+	if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+		ref_freq = dclk;
+	} else {
+		ref_freq = 96000;
+
+		/* If SSC is enabled, then the reference frequency needs to be
+		 * 100000 instead of 96000.
+		 */
+		for(index = 0; index < port->attr_list->num_attrs; index++) {
+			if(port->attr_list->attr[index].id == PD_ATTR_ID_SSC) {
+				ref_freq = 100000;
+				break;
+			}
+		}
+	}
+	/* LVDS reference clock can be 96 or 100 MHz. However there
+	 * are no mention in the specification to specify which register
+	 * to select/set this.
+	 */
+
+	/* When the clock source is provided externally by the port driver,
+	 * the allowed error range is 0. */
+	if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+		ret = get_clock(dclk, ref_freq, &m1, &m2, &n, &p, 0
+				,port->port_type,dual_channel);
+	} else {
+		ret = get_clock(dclk, ref_freq, &m1, &m2, &n, &p, TARGET_ERROR
+				,port->port_type,dual_channel);
+	}
+
+	if(ret) {
+		EMGD_ERROR("Clock %ld could not be programmed", dclk);
+		return ret;
+	}
+
+	/* Disable DPLL, Write an 0x80 into P for saftey */
+	control = 0x10000000 | (0x80<<clock->p_shift) | BIT26 | vga_mult;
+	WRITE_MMIO_REG(display, clock->dpll_control, control);
+
+	/* Program N, M1,and M2 */
+	WRITE_MMIO_REG(display, clock->mnp, (n<<16) | (m1<<8) | m2);
+
+	/* Enable DPLL, Disable VGAm Mode and sitck in new P values */
+	if(port->port_type==IGD_PORT_LVDS){
+		/* If LVDS set the appropriate bits for mode select */
+		control = (BIT31 | BIT28 | BIT27 )
+			| (p<<clock->p_shift) | vga_mult;
+
+		if(port->attr_list) {
+
+			for(index = 0; index < port->attr_list->num_attrs; index++) {
+
+				/* Set spread spectrum and pulse phase */
+				if(port->attr_list->attr[index].id == PD_ATTR_ID_SSC) {
+
+					/*
+					 * Pulse Phase for Poulsbo only has valid values between
+					 * 3 and 9
+					 */
+					if(port->attr_list->attr[index].value >= 3 &&
+						port->attr_list->attr[index].value <= 9) {
+
+						control |= BIT13 | BIT14;
+						/*
+						 * Set the Pulse Phase to the clock phase specified by
+						 * the user
+						 */
+						control |= (port->attr_list->attr[index].value<<9);
+					}
+					break;
+				}
+			}
+		}
+	} else{
+	/* else DAC/SDVO */
+		control = (BIT31 | BIT28 | BIT26) | (p<<clock->p_shift) | vga_mult;
+	}
+	/*
+	 * Poulsbo has high speed clock on always
+	 */
+	control |= BIT30;
+
+
+
+	/* Set the clock source correctly based on PD settings */
+	if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+		control |= port->clock_bits;
+	} else {
+		control |= port->clock_bits & ~0x00006000;
+	}
+
+	/* sDVO Multiplier bits[7:0] */
+	if (port->port_type == IGD_PORT_DIGITAL) {
+
+		if (port_mult == 2) {
+
+			control |= (1 << 4);
+
+		} else if (port_mult == 4) {
+
+			control |= (3 << 4);
+		}
+	}
+
+	WRITE_MMIO_REG(display, clock->dpll_control, control);
+
+	/* We must wait for 150 us for the dpll clock to warm up */
+	OS_SLEEP(150);
+	PIPE(display)->dclk = dclk;
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/plb/kms_mode_plb.c b/drivers/gpu/drm/emgd/emgd/display/mode/plb/kms_mode_plb.c
new file mode 100644
index 0000000..ec1546d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/plb/kms_mode_plb.c
@@ -0,0 +1,1102 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: kms_mode_plb.c
+ * $Revision: 1.2 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2011, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+
+#include <igd.h>
+#include <igd_pwr.h>
+#include <vga.h>
+#include <pi.h>
+#include <plb/regs.h>
+#include "drm_emgd_private.h"
+#include "../cmn/mode_dispatch.h"
+#include "../cmn/match.h"
+#include "mode_plb.h"
+#include <math_fix.h>
+#include <memory.h>
+
+
+/*------------------------------------------------------------------------------
+ * Function Prototypes
+ *----------------------------------------------------------------------------*/
+int kms_mode_get_stride_stereo_plb(igd_display_pipe_t *pipe,
+		igd_display_plane_t *plane,
+		unsigned long *stride,
+		unsigned long *stereo,
+		unsigned long flags);
+void kms_program_pipe_vga_plb(emgd_crtc_t *emgd_crtc);
+static void kms_program_pipe_plb(emgd_crtc_t *emgd_crtc);
+static void kms_set_pipe_pwr_plb(emgd_crtc_t *emgd_crtc, unsigned long enable);
+static void kms_program_plane_plb(emgd_crtc_t *emgd_crtc, unsigned long status);
+static void kms_set_plane_pwr_plb(emgd_crtc_t *emgd_crtc, unsigned long enable);
+static int set_color_correct_plb(emgd_crtc_t *emgd_crtc);
+
+
+extern int kms_program_clock_plb(emgd_crtc_t *emgd_crtc,
+	igd_clock_t *clock, unsigned long dclk);
+extern int wait_for_vblank_plb(unsigned char *mmio,
+	unsigned long pipe_reg);
+extern void kms_program_pipe_vga(emgd_crtc_t *emgd_crtc,
+	igd_timing_info_t *timings);
+extern void disable_vga_plb(unsigned char *mmio);
+
+
+/*------------------------------------------------------------------------------
+ * Global Variables
+ *----------------------------------------------------------------------------*/
+extern mode_data_plb_t device_data_plb[1];
+
+
+/*------------------------------------------------------------------------------
+ * KMS Dispatch Table
+ *----------------------------------------------------------------------------*/
+mode_kms_dispatch_t mode_kms_dispatch_plb = {
+	kms_program_pipe_plb,
+	kms_set_pipe_pwr_plb,
+	kms_program_plane_plb,
+	kms_set_plane_pwr_plb,
+	NULL,
+	NULL,
+	NULL,                       /* kms_get_vblank_counter */
+	kms_match_mode,
+};
+
+
+/*!
+ * Get the stride and stereo values based on the display.  This is also used
+ * by the MI instructions.
+ *
+ * @param pipe Pointer to hardware device instance data
+ * @param plane Pointer to hardware device instance data
+ * @param stride
+ * @param stereo
+ * @param flags Should the stereo be for the frontbuffer or backbuffer?
+ *
+ * @return stride - Stride of the display
+ * @return stereo - Stereo address of the display
+ */
+int kms_mode_get_stride_stereo_plb(igd_display_pipe_t *pipe,
+	igd_display_plane_t *plane,
+	unsigned long *stride,
+	unsigned long *stereo,
+	unsigned long flags)
+{
+	unsigned long pitch = plane->fb_info->screen_pitch;
+	igd_timing_info_t *timing = pipe->timing;
+	unsigned long base_offset;
+
+	base_offset = plane->fb_info->visible_offset;
+
+	*stride = pitch;
+	*stereo = 0;
+
+	/* For field replication, valid for interlaced modes only
+	 *     set stereo = fb_base,
+	 *         stride = pitch
+	 */
+	if (timing->mode_info_flags & IGD_SCAN_INTERLACE) {
+
+		if(timing->mode_info_flags & IGD_LINE_DOUBLE) {
+			/* Interlaced + Line double flags means field replication.
+			 * same lines are sent for both fields. Program the
+			 * second eye to be same as the first.
+			 */
+			*stereo = base_offset;
+		} else {
+			/* Regular interlaced. Second eye starts on line 2.
+			 * Skip every other line.
+			 */
+			*stereo = base_offset + pitch;
+			*stride = pitch * 2;
+		}
+	}
+
+	return 0;
+}
+
+
+
+/*!
+ *
+ * @param emgd_crtc
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL if color attributes not found
+ */
+static int set_color_correct_plb(emgd_crtc_t *emgd_crtc)
+{
+	const int        MID_PIXEL_VAL    = 125;
+	const int        MAX_PIXEL_VAL    = 255;
+	const int        NUM_PALETTE_ENTRIES = 256;
+
+	struct drm_device  *dev = NULL;
+	igd_context_t      *context = NULL;
+	igd_display_port_t *port = NULL;
+	igd_display_pipe_t *pipe = NULL;
+	struct drm_encoder *encoder = NULL;
+	emgd_encoder_t     *emgd_encoder = NULL;
+
+	unsigned int     gamma_r_max_24i_8f, gamma_r_min_24i_8f;
+	unsigned int     gamma_g_max_24i_8f, gamma_g_min_24i_8f;
+	unsigned int     gamma_b_max_24i_8f, gamma_b_min_24i_8f;
+	unsigned int     new_gamma_r_24i_8f, new_gamma_g_24i_8f;
+	unsigned int     new_gamma_b_24i_8f;
+	unsigned int     gamma_normal_r_24i_8f, gamma_normal_g_24i_8f;
+	unsigned int     gamma_normal_b_24i_8f;
+	int              brightness_factor_r, brightness_factor_g;
+	int              brightness_factor_b;
+	int              contrast_factor_r, contrast_factor_g;
+	int              contrast_factor_b;
+
+	unsigned int      *palette;
+	unsigned int      i;
+
+	igd_range_attr_t *gamma_attr      = NULL, *contrast_attr = NULL;
+	igd_range_attr_t *brightness_attr = NULL;
+	igd_attr_t       *hal_attr_list   = NULL;
+
+	EMGD_TRACE_ENTER;
+
+	pipe = emgd_crtc->igd_pipe;
+	dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (((struct drm_crtc *)(&emgd_crtc->base)) == encoder->crtc) {
+			emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+			port = emgd_encoder->igd_port;
+			break;
+		}
+	}
+	if (!port) {
+		EMGD_ERROR_EXIT("No port being used.");
+		return -IGD_ERROR_INVAL;
+	}
+	hal_attr_list  = port->attributes;
+
+	/* Using OS_ALLOC to avoid using > 1024 on stack (frame size warning ) */
+	palette = OS_ALLOC(sizeof (unsigned int) * NUM_PALETTE_ENTRIES);
+
+	/* start with a fresh palette */
+	for (i = 0; i < NUM_PALETTE_ENTRIES; i++) {
+		palette[i] = (i << 16) | (i << 8) | i;
+	}
+
+	/* get a pointer to gamma, contrast, and brightness attr */
+	i = 0;
+
+	while (PD_ATTR_LIST_END != hal_attr_list[i].id) {
+		switch (hal_attr_list[i].id) {
+		case PD_ATTR_ID_FB_GAMMA:
+			gamma_attr      = (igd_range_attr_t *) &hal_attr_list[i];
+			break;
+
+		case PD_ATTR_ID_FB_BRIGHTNESS:
+			brightness_attr = (igd_range_attr_t *) &hal_attr_list[i];
+			break;
+
+		case PD_ATTR_ID_FB_CONTRAST:
+			contrast_attr   = (igd_range_attr_t *) &hal_attr_list[i];
+			break;
+
+		default:
+			break;
+		}
+
+		i++;
+	}
+
+	if(!gamma_attr || !brightness_attr || !contrast_attr) {
+		EMGD_ERROR("Color Correction Atrributes not found!");
+		return -IGD_ERROR_INVAL;
+	}
+
+	/* Get the max and min */
+	gamma_r_max_24i_8f = ((gamma_attr->max >> 16) & 0xFF) << 3;
+	gamma_g_max_24i_8f = ((gamma_attr->max >>  8) & 0xFF) << 3;
+	gamma_b_max_24i_8f =  (gamma_attr->max        & 0xFF) << 3;
+
+	gamma_r_min_24i_8f = ((gamma_attr->min >> 16) & 0xFF) << 3;
+	gamma_g_min_24i_8f = ((gamma_attr->min >>  8) & 0xFF) << 3;
+	gamma_b_min_24i_8f =  (gamma_attr->min        & 0xFF) << 3;
+
+	/* The new gamma values are in 3i.5f format, but we must convert it
+	 * to 24i.8f format before passing it to OS_POW_FIX
+	 */
+	new_gamma_r_24i_8f = ((gamma_attr->current_value >> 16) & 0xFF) << 3;
+	new_gamma_g_24i_8f = ((gamma_attr->current_value >> 8) & 0xFF) << 3;
+	new_gamma_b_24i_8f = (gamma_attr->current_value & 0xFF) << 3;
+
+	/* make sure the new gamma is within range */
+	new_gamma_r_24i_8f = OS_MIN(gamma_r_max_24i_8f, new_gamma_r_24i_8f);
+	new_gamma_r_24i_8f = OS_MAX(gamma_r_min_24i_8f, new_gamma_r_24i_8f);
+	new_gamma_g_24i_8f = OS_MIN(gamma_g_max_24i_8f, new_gamma_g_24i_8f);
+	new_gamma_g_24i_8f = OS_MAX(gamma_g_min_24i_8f, new_gamma_g_24i_8f);
+	new_gamma_b_24i_8f = OS_MIN(gamma_b_max_24i_8f, new_gamma_b_24i_8f);
+	new_gamma_b_24i_8f = OS_MAX(gamma_b_min_24i_8f, new_gamma_b_24i_8f);
+
+
+	gamma_normal_r_24i_8f =
+		OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_r_24i_8f);
+
+	gamma_normal_g_24i_8f =
+		OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_g_24i_8f);
+
+	gamma_normal_b_24i_8f =
+		OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_b_24i_8f);
+
+	for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+		unsigned int new_gamma;
+		unsigned int cur_color;
+		unsigned int cur_palette = palette[i];
+
+		/* Note that we do not try to calculate the gamma if it
+		 * is 1.0, e.g. 0x100.  This is to avoid round-off errors
+		 */
+
+		/* red: calculate and make sure the result is within range */
+		if (0x100 != new_gamma_r_24i_8f) {
+			cur_color  = (cur_palette >> 16) & 0xFF;
+			new_gamma  = OS_POW_FIX(cur_color, (1<<16)/new_gamma_r_24i_8f);
+			new_gamma  = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_r_24i_8f;
+			palette[i] &= 0x00FFFF;
+			palette[i] |=
+				(OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF) << 16;
+		}
+
+		/* green: calculate and make sure the result is within range */
+		if (0x100 != new_gamma_g_24i_8f) {
+			cur_color  = (cur_palette >> 8) & 0xFF;
+			new_gamma  = OS_POW_FIX(cur_color, (1<<16)/new_gamma_g_24i_8f);
+			new_gamma  = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_g_24i_8f;
+			palette[i] &= 0xFF00FF;
+			palette[i] |=
+				(OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF) << 8;
+		}
+
+		/* blue: calculate and make sure the result is within range */
+		if (0x100 != new_gamma_b_24i_8f) {
+			cur_color  = cur_palette & 0xFF;
+			new_gamma  = OS_POW_FIX(cur_color, (1<<16)/new_gamma_b_24i_8f);
+			new_gamma  = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_b_24i_8f;
+			palette[i] &= 0xFFFF00;
+			palette[i] |=
+				(OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF);
+		}
+	}
+
+
+	/* Brightness correction */
+	brightness_factor_r = (brightness_attr->current_value >> 16) & 0xFF;
+	brightness_factor_g = (brightness_attr->current_value >> 8) & 0xFF;
+	brightness_factor_b = brightness_attr->current_value & 0xFF;
+
+	/* The factors are offset by 0x80 because 0x80 is 0 correction */
+	brightness_factor_r -= 0x80;
+	brightness_factor_g -= 0x80;
+	brightness_factor_b -= 0x80;
+
+	for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+		int          new_pixel_val;
+		unsigned int cur_color;
+		unsigned int cur_palette = palette[i];
+
+		/* red: calculate and make sure the result is within range */
+		cur_color     =  (cur_palette >> 16) & 0xFF;
+		new_pixel_val =  cur_color + brightness_factor_r;
+		new_pixel_val =  OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+		palette[i]    &= 0x00FFFF;
+		palette[i]    |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 16;
+
+		/* green: calculate and make sure the result is within range */
+		cur_color     =  (cur_palette >> 8) & 0xFF;
+		new_pixel_val =  cur_color + brightness_factor_g;
+		new_pixel_val =  OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+		palette[i]    &= 0xFF00FF;
+		palette[i]    |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 8;
+
+		/* blue: calculate and make sure the result is within range */
+		cur_color     =  cur_palette & 0xFF;
+		new_pixel_val =  cur_color + brightness_factor_b;
+		new_pixel_val =  OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+		palette[i]    &= 0xFFFF00;
+		palette[i]    |= OS_MAX(new_pixel_val, 0) & 0xFF;
+	}
+
+
+	/* contrast correction */
+	contrast_factor_r = (contrast_attr->current_value >> 16) & 0xFF;
+	contrast_factor_g = (contrast_attr->current_value >> 8) & 0xFF;
+	contrast_factor_b = contrast_attr->current_value & 0xFF;
+
+	/* make sure values are within range */
+	contrast_factor_r -= 0x80;
+	contrast_factor_g -= 0x80;
+	contrast_factor_b -= 0x80;
+
+
+	/* We're doing integer division in this loop using 16i.16f
+	 * integers.  The result will then be converted back into a
+	 * regular, 32-bit integer
+	 */
+	for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+		int new_pixel_val;
+		unsigned int cur_color;
+		unsigned int cur_palette = palette[i];
+
+		/* red: calculate and make sure the result is within range */
+		if (0 != contrast_factor_r ) {
+			cur_color     = (cur_palette >> 16) & 0xFF;
+			new_pixel_val =
+				(MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_r);
+			new_pixel_val =   new_pixel_val * (cur_color - MID_PIXEL_VAL);
+			new_pixel_val >>= 16;  /* convert back to 32i format */
+			new_pixel_val +=  MID_PIXEL_VAL;
+			new_pixel_val =   OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+			palette[i]    &=  0x00FFFF;  /* clear out the R color */
+			palette[i]    |=  (OS_MAX(new_pixel_val, 0) & 0xFF) << 16;
+		}
+
+		/* green: calculate and make sure the result is within range */
+		if (0 != contrast_factor_g ) {
+			cur_color     = (cur_palette >> 8) & 0xFF;
+			new_pixel_val =
+				(MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_g);
+			new_pixel_val =   new_pixel_val * (cur_color - MID_PIXEL_VAL);
+			new_pixel_val >>= 16;  /* convert back to 32i format */
+			new_pixel_val +=  MID_PIXEL_VAL;
+			new_pixel_val =   OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+			palette[i]    &=  0xFF00FF;  /* clear out the G color */
+			palette[i]    |=  (OS_MAX(new_pixel_val, 0) & 0xFF) << 8;
+		}
+
+		/* blue: calculate and make sure the result is within range */
+		if (0 != contrast_factor_b) {
+			cur_color     = cur_palette & 0xFF;
+			new_pixel_val =
+				(MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_b);
+			new_pixel_val =   new_pixel_val * (cur_color - MID_PIXEL_VAL);
+			new_pixel_val >>= 16;  /* convert back to 32i format */
+			new_pixel_val +=  MID_PIXEL_VAL;
+			new_pixel_val =   OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+			palette[i]    &=  0xFFFF00;  /* clear out the B color */
+			palette[i]    |=   OS_MAX(new_pixel_val, 0) & 0xFF;
+		}
+	}
+
+
+	/* write the new values in the palette */
+	for (i = 0; i < NUM_PALETTE_ENTRIES; i++) {
+		EMGD_WRITE32(palette[i], context->device_context.virt_mmadr +
+			pipe->palette_reg + i*4);
+	}
+	OS_FREE(palette);
+
+	return 0;
+}
+
+
+
+/*!
+ *
+ * @param emgd_crtc Pointer to hardware device instance data
+ *
+ * @return void
+ */
+void kms_program_pipe_vga_plb(
+	emgd_crtc_t *emgd_crtc)
+{
+	struct drm_device  *dev          = NULL;
+	igd_timing_info_t  *timing       = NULL;
+	igd_display_pipe_t *pipe         = NULL;
+	igd_context_t      *context      = NULL;
+	struct drm_encoder *encoder      = NULL;
+	emgd_encoder_t     *emgd_encoder = NULL;
+	igd_display_port_t *port         = NULL;
+	unsigned long vga_control;
+	unsigned long upscale = 0;
+	int centering = 1;
+
+	EMGD_TRACE_ENTER;
+
+	pipe = emgd_crtc->igd_pipe;
+	dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (((struct drm_crtc *)(&emgd_crtc->base)) == encoder->crtc) {
+			emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+			port = emgd_encoder->igd_port;
+			break;
+		}
+	}
+
+#ifdef CONFIG_MICRO
+	/*
+	 * We cannot set a VGA mode unless the display planes are turned off.
+     * This becomes evident during a Windows BSOD.  Since neither Windows
+     * nor IEGD got a chance to turn off these registers, and the VGA mode was
+     * set by the VBIOS, the screen gets corrupted.  In order to fix this
+     * problem, we will turn the cursor and display planes here.
+     *
+     * Note: Removing previous partial-fix in favor of this complete one.
+	 */
+    /* Cursor A */
+	EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x70080);
+	EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x70084);
+    /* Cursor B */
+	EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x700C0);
+	EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x700C4);
+    /* Display A */
+	EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x70180);
+	EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x70184);
+    /* Display B */
+	EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x71180);
+	EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x71184);
+    /* Display C */
+	EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x72180);
+	EMGD_WRITE32(0, context->device_context.virt_mmadr + 0x72184);
+#endif
+
+	/*
+	 * VGA Plane can attach to only one pipe at a time. LVDS can
+	 * only attach to pipe B. We need to use the display passed to
+	 * determine the pipe number to use. (Plba is same as Alm).
+	 */
+
+	/*
+	 * We can come here with following cases:
+	 *   1. magic->vga    CRT, DVI type displays
+	 *   2. native->vga   int-lvds, and up-scaling lvds displays
+	 *   3. pipe->vga     TV and other unscaled-lvds displays
+	 */
+	vga_control = EMGD_READ32(context->device_context.virt_mmadr + 0x71400);
+	vga_control &= 0x18e3ff00;
+	vga_control |= 0x8e;
+
+	timing = pipe->timing;
+	if(!timing->extn_ptr) {
+		EMGD_ERROR_EXIT("No Extension pointer in program_pipe_vga_plb");
+		return;
+	}
+
+	if (port) {
+		/* Find UPSCALING attr value*/
+		pi_pd_find_attr_and_value(port,
+			PD_ATTR_ID_PANEL_FIT,
+			0,/*no PD_FLAG for UPSCALING */
+			NULL, /* dont need the attr ptr*/
+			&upscale);
+		/* this PI func will not modify value of upscale if attr does not exist */
+	}
+
+	/* magic->vga or native->vga cases */
+	if ((timing->width == 720 && timing->height == 400) || upscale) {
+		centering = 0;
+	}
+
+	/* Enable border */
+	if((timing->width >= 800) && !upscale) {
+		EMGD_DEBUG("Enable VGA Border");
+		vga_control |= (1L<<26);
+	}
+
+	if(timing->width == 640) {
+		EMGD_DEBUG("Enable Nine Dot Disable");
+		vga_control |= (1L<<18);
+	}
+
+	if(centering) {
+		EMGD_DEBUG("Enable VGA Center Centering");
+		vga_control |= 1L<<24;
+
+		if(timing->height >= 960) {
+			if(timing->width >= 1280) {
+				EMGD_DEBUG("Enable VGA 2x (Nine Dot Disable)");
+				vga_control |= (1L<<30) | (1L<<18);
+			}
+		}
+	} else {
+		if (port) {
+			if(port->port_type == IGD_PORT_LVDS) {
+				EMGD_DEBUG("Enable VGA Upper-Left Centering & Nine Dot Disable");
+				vga_control |= (1L<<25 | (1L<<18));
+			} else if (upscale) {
+				EMGD_DEBUG("Enable VGA Center Upper-left for upscale ports");
+				vga_control |= 1L<<25;
+			}
+		}
+	}
+
+	if(pipe->pipe_num) {
+		vga_control |= 1L<<29;
+	}
+
+	kms_program_pipe_vga(emgd_crtc, (igd_timing_info_t *)timing->extn_ptr);
+	EMGD_WRITE32(vga_control, context->device_context.virt_mmadr + 0x71400);
+
+	EMGD_TRACE_EXIT;
+	return;
+}
+
+
+
+/**
+ * kms_set_pipe_pwr_plb
+ *
+ * Turns the pipe ON or OFF depending on the input
+ *
+ * @param emgd_crtc (IN) specifies the pipe to change
+ * @param enable    (IN) TRUE to enable pipe, FALSE to disable
+ *
+ * @return
+ */
+static void kms_set_pipe_pwr_plb(emgd_crtc_t *emgd_crtc, unsigned long enable)
+{
+	unsigned long       pipe_conf;
+	struct drm_device  *dev;
+	igd_display_pipe_t *pipe;
+	igd_context_t      *context;
+
+
+	EMGD_TRACE_ENTER;
+
+
+	dev       = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+	context   = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+	pipe      = emgd_crtc->igd_pipe;
+	pipe_conf = device_data_plb->pipe_preserve &
+		EMGD_READ32(context->device_context.virt_mmadr + pipe->pipe_reg);
+
+
+	/* Do nothing if current power state is same as what we want to set */
+	/* The PIPE_ENABLE bit is at bit-position 31 */
+	if ( (enable << 31) == (pipe_conf & PIPE_ENABLE) ){
+
+		EMGD_TRACE_EXIT;
+		return;
+	}
+
+
+	if (!enable) {
+		/* Disable pipe */
+		EMGD_WRITE32(pipe_conf & ~PIPE_ENABLE,
+			context->device_context.virt_mmadr + pipe->pipe_reg);
+
+		EMGD_DEBUG("Set Pipe Power: OFF");
+
+	} else {
+		/* Enable pipe */
+		EMGD_WRITE32(pipe_conf | PIPE_ENABLE,
+			context->device_context.virt_mmadr + pipe->pipe_reg);
+
+		EMGD_DEBUG("Set Pipe Power: ON");
+	}
+
+
+	EMGD_TRACE_EXIT;
+	return;
+}
+
+
+
+/*!
+ * This function programs the Timing registers and clock registers and
+ * other control registers for PIPE.
+ *
+ * @param emgd_crtc
+ * @param status
+ *
+ * @return void
+ */
+static void kms_program_pipe_plb(emgd_crtc_t *emgd_crtc)
+{
+	unsigned long       timing_reg;
+	unsigned long       pipe_conf;
+	unsigned long       hactive, vactive;
+	igd_timing_info_t  *pTimings;
+	unsigned long       temp;
+	struct drm_device  *dev     = NULL;
+	igd_context_t      *context = NULL;
+	igd_display_pipe_t *pipe    = NULL;
+	igd_display_port_t *port    = NULL;
+	int i;
+
+	EMGD_TRACE_ENTER;
+
+
+	pipe = emgd_crtc->igd_pipe;
+	dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+	EMGD_DEBUG("Device power state: D%ld", context->device_context.power_state);
+
+	pipe_conf = device_data_plb->pipe_preserve &
+		EMGD_READ32(context->device_context.virt_mmadr + pipe->pipe_reg);
+
+	/* Reset the plane of this pipe back to NULL, it will be set on the
+	 * call to program_plane, which is ok, since program_pipe occurs
+	 * before program_plane */
+	pipe->plane = NULL;
+
+	pTimings = pipe->timing;
+
+	/*
+	 * If the mode is VGA and the PD says it handles all VGA modes without
+	 * reprogramming then just set the mode and leave centering off.
+	 */
+	if(pTimings->mode_info_flags & IGD_MODE_VESA) {
+		if (pTimings->mode_number <= VGA_MODE_NUM_MAX) {
+			/* Pipe timings and clocks are not used but it must be on anyway */
+			EMGD_WRITE32(pipe_conf | 0x80000000,
+				context->device_context.virt_mmadr + pipe->pipe_reg);
+
+			kms_program_pipe_vga_plb(emgd_crtc);
+			return;
+		}
+	}
+
+	/* Program dot clock divisors. */
+	kms_program_clock_plb(emgd_crtc, pipe->clock_reg, pTimings->dclk);
+
+	/* Program timing registers for the pipe */
+	timing_reg = pipe->timing_reg;
+	if (pTimings->mode_info_flags & IGD_PIXEL_DOUBLE) {
+		hactive = (unsigned long)pTimings->width*2 - 1;
+	} else {
+		hactive = (unsigned long)pTimings->width - 1;
+	}
+
+	if (pTimings->mode_info_flags & IGD_LINE_DOUBLE) {
+		if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) {
+			vactive = (unsigned long)pTimings->height - 1;
+		} else {
+			vactive = (unsigned long)pTimings->height*2 - 1;
+		}
+	} else {
+		if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) {
+			vactive = (unsigned long)pTimings->height/2 - 1;
+		} else {
+			vactive = (unsigned long)pTimings->height - 1;
+		}
+	}
+
+	/*
+	 * DPLL should be on at this point which is required for touching
+	 * the palette.
+	 */
+	/* reset the palette */
+	for (i = 0; i < 256; i++) {
+		EMGD_WRITE32(((i<<16) | (i<<8) | i),
+			context->device_context.virt_mmadr + pipe->palette_reg + i*4);
+	}
+
+	/* apply color correction */
+	for( i = 0; PD_ATTR_LIST_END != port->attributes[i].id; i++ ) {
+
+		if ((PD_ATTR_ID_FB_GAMMA      == (port->attributes[i].id)) ||
+			(PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)) ||
+			(PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)))  {
+
+			set_color_correct_plb(emgd_crtc);
+		}
+	}
+
+
+	/*
+	 * NOTE: For size reasons the timng table contains unsigned short
+	 * values. Don't shift them past 16. Use a temp instead.
+	 * All register offsets and bit shift are verified for Napa
+	 */
+	temp = ((unsigned long)pTimings->htotal << 16) | hactive;
+	EMGD_WRITE32(temp, context->device_context.virt_mmadr + timing_reg);
+
+	temp = ((unsigned long)pTimings->hblank_end << 16) |
+		(unsigned long)pTimings->hblank_start;
+	EMGD_WRITE32(temp, context->device_context.virt_mmadr + timing_reg + 0x04);
+
+	temp = ((unsigned long)pTimings->hsync_end << 16) |
+		(unsigned long)pTimings->hsync_start;
+	EMGD_WRITE32(temp, context->device_context.virt_mmadr + timing_reg + 0x08);
+
+	temp = ((unsigned long)pTimings->vtotal << 16) | vactive;
+	EMGD_WRITE32(temp, context->device_context.virt_mmadr + timing_reg + 0x0C);
+
+	temp = ((unsigned long)pTimings->vblank_end << 16) |
+		(unsigned long)pTimings->vblank_start;
+	EMGD_WRITE32(temp, context->device_context.virt_mmadr + timing_reg + 0x10);
+
+	temp = ((unsigned long)pTimings->vsync_end << 16) |
+		(unsigned long)pTimings->vsync_start;
+	EMGD_WRITE32(temp, context->device_context.virt_mmadr + timing_reg + 0x14);
+
+	/*
+	 * If there is a linked mode it is either the VGA or a scaled
+	 * mode. If it is scaled then we need to use it as the source size.
+	 */
+	if(pTimings->extn_ptr) {
+		igd_timing_info_t *scaled_timings =
+			(igd_timing_info_t *)pTimings->extn_ptr;
+		if((scaled_timings->mode_info_flags & IGD_MODE_VESA) &&
+			(scaled_timings->mode_number <= VGA_MODE_NUM_MAX)) {
+			temp = (hactive << 16) | vactive;
+		} else {
+			temp = (unsigned long)scaled_timings->width  - 1;
+			temp = (temp << 16) |
+				(unsigned long)(scaled_timings->height - 1);
+		}
+	} else {
+		temp = (hactive << 16) | vactive;
+	}
+	EMGD_WRITE32(temp, context->device_context.virt_mmadr + timing_reg + 0x1C);
+
+	/* Set other registers */
+
+	/*
+	 * FIXME: max_dclk needs to be determined from core clock
+	 * at init time. 915 etc has several skus with different
+	 * clocks for the same device ID.
+	 *
+	 */
+
+	/* These values are derived from the Poulsbo B-Spec as
+	 * the suggested values */
+	EMGD_WRITE32(device_data_plb->fw_blc1,
+		context->device_context.virt_mmadr + FW_BLC1);
+	EMGD_WRITE32(device_data_plb->fw_blc2,
+		context->device_context.virt_mmadr + FW_BLC2);
+	EMGD_WRITE32(device_data_plb->fw_blc3,
+		context->device_context.virt_mmadr + FW_BLC3);
+	EMGD_WRITE32(device_data_plb->fw_self,
+		context->device_context.virt_mmadr + FW_BLC_SELF);
+	EMGD_WRITE32(device_data_plb->dsp_arb,
+		context->device_context.virt_mmadr + PIPEA_DISP_ARB_CTRL);
+
+	/* The SGX 2D engine can saturate the memory bus and starve
+	 * the display engine causing visible screen tearing.
+	 * This reduces the priority of the SGX vs. display engine
+	 */
+	temp = EMGD_READ32(context->device_context.virt_mmadr + G_DEBUG);
+	EMGD_WRITE32((temp | (1 << 11)),
+		context->device_context.virt_mmadr + G_DEBUG);
+
+	EMGD_WRITE32(pipe_conf,
+		context->device_context.virt_mmadr + pipe->pipe_reg);
+
+	/*
+	 * Set the VGA address range to 0xa0000 so that a normal (not VGA)
+	 * mode can be accessed through 0xa0000 in a 16bit world.
+	 */
+	WRITE_AR(context->device_context.virt_mmadr, 0x10, 0xb);
+	WRITE_VGA(context->device_context.virt_mmadr, GR_PORT, 0x06, 0x5);
+	WRITE_VGA(context->device_context.virt_mmadr, GR_PORT, 0x10, 0x1);
+
+	if(pTimings->extn_ptr) {
+		/* This means either internal scaling (LVDS) or centered VGA */
+		pTimings = pTimings->extn_ptr;
+		if(pTimings->extn_ptr) {
+			/* This is both the scaled and centered VGA */
+			pTimings = pTimings->extn_ptr;
+		}
+		if(pTimings->mode_info_flags & IGD_MODE_VESA) {
+			if (pTimings->mode_number <= VGA_MODE_NUM_MAX) {
+				kms_program_pipe_vga_plb(emgd_crtc);
+			}
+		}
+	}
+
+	EMGD_TRACE_EXIT;
+	return;
+}
+
+
+
+/*!
+ * kms_set_plane_pwr_plb
+ *
+ * Enables or disables the plane associated with the given CRTC
+ *
+ * @param enable [IN] turns the plane on or off
+ *
+ * @return void
+ */
+static void kms_set_plane_pwr_plb(emgd_crtc_t *emgd_crtc, unsigned long enable)
+{
+	unsigned long           plane_control;
+	unsigned long           plane_reg;
+	struct drm_device      *dev         = NULL;
+	igd_display_plane_t    *plane       = NULL;
+	igd_display_pipe_t     *pipe        = NULL;
+	igd_context_t          *context     = NULL;
+
+	EMGD_TRACE_ENTER;
+
+	EMGD_DEBUG("Program Plane: %s", enable?"ENABLE":"DISABLE");
+
+	pipe    = emgd_crtc->igd_pipe;
+	dev     = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+	plane   = PLANE(pipe->owner);
+
+	if (!plane) {
+		EMGD_ERROR_EXIT("Trying to set power to a plane that is not tied "
+			" to a crtc.");
+		return;
+	}
+
+	/* In case a plane update is already in progress */
+	wait_for_vblank_plb(context->device_context.virt_mmadr, pipe->pipe_reg);
+
+	/* Get the current value of the plane control register */
+	plane_reg     = plane->plane_reg;
+	plane_control = EMGD_READ32(context->device_context.virt_mmadr + plane_reg);
+
+	if(plane->plane_reg == DSPACNTR) {
+		plane_control &= device_data_plb->plane_a_preserve;
+	} else { /* if it's plane b or plane c */
+		plane_control &= device_data_plb->plane_b_c_preserve;
+	}
+
+
+	if((enable == FALSE) ||
+		(context->device_context.power_state != IGD_POWERSTATE_D0)) {
+
+		/*
+		 * Note: The vga programming code does not have an "off". So
+		 * when programming the plane to off we make sure VGA is off
+		 * as well.
+		 */
+		disable_vga_plb(context->device_context.virt_mmadr);
+
+		/*
+		 * To turn off plane A or B, the program have to trigger the plane A
+		 * or B start register.  Or else, it will not work.
+		 */
+		plane_control &= 0xEFFFFFFF;
+
+		EMGD_WRITE32(plane_control,
+						context->device_context.virt_mmadr + plane_reg);
+
+		EMGD_WRITE32(EMGD_READ32(context->device_context.virt_mmadr +
+			plane_reg + DSP_START_OFFSET),
+			context->device_context.virt_mmadr + plane_reg + DSP_START_OFFSET);
+	} else {
+		/* Enable Pipe */
+		plane_control |= 0x80000000;
+
+		EMGD_WRITE32(plane_control,
+			context->device_context.virt_mmadr + plane_reg);
+	}
+
+
+	wait_for_vblank_plb(context->device_context.virt_mmadr, pipe->pipe_reg);
+	EMGD_TRACE_EXIT;
+
+	return;
+}
+
+
+
+/*!
+ * Program Display Plane Values.
+ *
+ * @param emgd_crtc Pointer to hardware device instance data
+ *
+ * @return void
+ */
+static void kms_program_plane_plb(emgd_crtc_t *emgd_crtc,
+	unsigned long status)
+{
+	unsigned long stereo;
+	unsigned long stride;
+	unsigned long size;
+	unsigned long plane_control;
+	unsigned long plane_reg;
+	unsigned long start_addr_reg;
+	igd_timing_info_t      *timing  = NULL;
+	struct drm_device      *dev     = NULL;
+	igd_display_plane_t    *plane   = NULL;
+	igd_display_pipe_t     *pipe    = NULL;
+	igd_context_t          *context = NULL;
+	igd_framebuffer_info_t *fb_info = NULL;
+
+	EMGD_TRACE_ENTER;
+
+	pipe = emgd_crtc->igd_pipe;
+	dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+	plane   = PLANE(pipe->owner);
+	fb_info = plane->fb_info;
+	plane_reg = plane->plane_reg;
+	start_addr_reg = DSPAADDR;
+
+	EMGD_DEBUG("Device power state: D%ld", context->device_context.power_state);
+
+	wait_for_vblank_plb(context->device_context.virt_mmadr, pipe->pipe_reg);
+
+	plane_control = EMGD_READ32(context->device_context.virt_mmadr + plane_reg);
+	if(plane->plane_reg == DSPACNTR) {
+		plane_control &= device_data_plb->plane_a_preserve;
+	}
+	else { /* if it's plane b or plane c */
+		plane_control &= device_data_plb->plane_b_c_preserve;
+		start_addr_reg = 0x71184;
+	}
+
+	if((status == FALSE) ||
+		(context->device_context.power_state != IGD_POWERSTATE_D0)) {
+
+		/*
+		 * Note: The vga programming code does not have an "off". So
+		 * when programming the plane to off we make sure VGA is off
+		 * as well.
+		 */
+		disable_vga_plb(context->device_context.virt_mmadr);
+
+		/*
+		 * To turn off plane A or B, the program have to triger the plane A or B
+		 * start register.  Or else, it will not work.
+		 */
+		EMGD_WRITE32(plane_control, context->device_context.virt_mmadr + plane_reg);
+		EMGD_WRITE32(EMGD_READ32(context->device_context.virt_mmadr + start_addr_reg),
+			context->device_context.virt_mmadr + start_addr_reg);
+
+		wait_for_vblank_plb(context->device_context.virt_mmadr, pipe->pipe_reg);
+		return;
+	}
+	/*
+	 * Note: The very first pass through this function will be with
+	 * status false and timings == NULL. Don't use the timings before
+	 * the check above.
+	 */
+	timing = pipe->timing;
+	/* There is a special case code for legacy VGA modes */
+	while (timing->extn_ptr) {
+		timing = (igd_timing_info_t *)timing->extn_ptr;
+	}
+	if(MODE_IS_VGA(timing)) {
+		kms_program_plane_vga(context->device_context.virt_mmadr, timing);
+		return;
+	}
+
+	disable_vga_plb(context->device_context.virt_mmadr);
+
+	size = (((unsigned long)timing->height - 1)<<16) |
+		(unsigned long)(timing->width - 1);
+
+	/* enable plane, select pipe, enable gamma correction logic */
+	plane_control |= 0x80000000 | (pipe->pipe_num<<24);
+	pipe->plane = plane;
+#ifndef CONFIG_MICRO
+	plane_control |= (1<<30);
+#endif
+
+	/* Here the settings:
+	 *   If line + pixel dbling, set 21,20 to 01b, and set Horz Multiply
+	 *   If line dbling only,    set 21,20 to 11b
+	 *   If pixel dbling only,   set 21,20 to 00b, but set Horz Multiply
+	 *   If no doubling,         set 21,20 to 00b (no Horz Multiply)
+	 * For pixel doubling
+	 *           --> both progressive/interlaced modes
+	 * For Line doubling
+	 *           --> progressive modes only
+	 */
+
+	if (!(timing->mode_info_flags & IGD_SCAN_INTERLACE)) {
+		/* Line doubling in progressive mode requires special bits */
+		if (timing->mode_info_flags & IGD_LINE_DOUBLE) {
+			/* BIT 20 for line & pixel doubling*/
+			plane_control |= BIT20;
+			/* check later, if no pixel doubling, set bit 21 too*/
+		}
+	}
+	if (timing->mode_info_flags & IGD_PIXEL_DOUBLE) {
+		/* Horz pixel multiply must be set for double */
+		plane_control |= BIT11;
+		/* TODO -> Plba can more than double,
+		It can 3X, 4X etc. These arent exposed now */
+	}
+	else if(plane_control & BIT20){
+		/* For line ONLY doubling, set bit 21 also '1' */
+		plane_control |= BIT21;
+	}
+
+	kms_mode_get_stride_stereo_plb(pipe, plane, &stride, &stereo, 0);
+
+	/* set color depth */
+	switch (IGD_PF_DEPTH(fb_info->pixel_format)) {
+	case PF_DEPTH_8:
+		plane_control |= BIT27 | BIT30;
+		break;
+	case PF_DEPTH_16:
+		plane_control |= BIT28 | BIT26;
+		break;
+	default:
+	case PF_DEPTH_32:
+		plane_control |= BIT28 | BIT27;
+		break;
+	}
+
+	if(fb_info->flags & IGD_ENABLE_DISPLAY_GAMMA) {
+		plane_control |= (BIT30);
+	}
+
+	EMGD_DEBUG(" Plane Control = 0x%lx", plane_control);
+	EMGD_DEBUG(" Plane Base = 0x%lx", fb_info->visible_offset);
+	EMGD_DEBUG(" Plane Pitch = 0x%lx", stride);
+	EMGD_DEBUG(" Plane Size = 0x%lx", size);
+
+	EMGD_WRITE32(stride, context->device_context.virt_mmadr + plane_reg + DSP_STRIDE_OFFSET);
+	/*
+	 * In reality this only exists for plane B. It doesn't seem to hurt
+	 * plane A so just do it anyway and save us another case.
+	 */
+	EMGD_WRITE32(size, context->device_context.virt_mmadr + plane_reg + DSP_SIZE_OFFSET);
+
+	/*EMGD_WRITE32(stereo, MMIO(display) + plane_reg + DSP_STEREO_OFFSET);
+		- This register is Reserved ON plba */
+	EMGD_WRITE32(fb_info->visible_offset,
+		context->device_context.virt_mmadr + plane_reg + DSP_START_OFFSET);
+
+	/* It seems we need push or trigger plane A/B to start to work
+	 * on Poulsbo, especially for sDVO port. Let's write plane control
+	 * register and start address register at last.
+	 */
+	EMGD_WRITE32(plane_control, context->device_context.virt_mmadr + plane_reg);
+	EMGD_WRITE32(EMGD_READ32(context->device_context.virt_mmadr + start_addr_reg),
+		context->device_context.virt_mmadr + start_addr_reg);
+
+	wait_for_vblank_plb(context->device_context.virt_mmadr, pipe->pipe_reg);
+
+	EMGD_TRACE_EXIT;
+	return;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/plb/micro_mode_plb.c b/drivers/gpu/drm/emgd/emgd/display/mode/plb/micro_mode_plb.c
new file mode 100644
index 0000000..9fbb378
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/plb/micro_mode_plb.c
@@ -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/drivers/gpu/drm/emgd/emgd/display/mode/plb/mode_plb.c b/drivers/gpu/drm/emgd/emgd/display/mode/plb/mode_plb.c
new file mode 100644
index 0000000..ac6ea5d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/plb/mode_plb.c
@@ -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/drivers/gpu/drm/emgd/emgd/display/mode/plb/mode_plb.h b/drivers/gpu/drm/emgd/emgd/display/mode/plb/mode_plb.h
new file mode 100644
index 0000000..0c42d29
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/plb/mode_plb.h
@@ -0,0 +1,47 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mode_plb.h
+ * $Revision: 1.2 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2011, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+
+#ifdef CONFIG_PLB
+
+typedef struct _mode_data_plb {
+	unsigned long plane_a_preserve;
+	unsigned long plane_b_c_preserve;
+	unsigned long pipe_preserve;
+	unsigned long port_preserve;
+	unsigned long fw_blc1;
+	unsigned long fw_blc2;
+	unsigned long fw_blc3;
+	unsigned long fw_self;
+	unsigned long mem_mode;
+	unsigned long dsp_arb;
+}mode_data_plb_t;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/tnc/clocks_tnc.c b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/clocks_tnc.c
new file mode 100644
index 0000000..8e58723
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/clocks_tnc.c
@@ -0,0 +1,1184 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: clocks_tnc.c
+ * $Revision: 1.18 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Clock programming for Atom E6xx
+ *  program clocks used for LVDS port based on Lincroft
+ *  program clocks used for SDVO port based on Atom E6xx overlay
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+#include <io.h>
+#include <sched.h>
+
+#include <igd_init.h>
+#include <igd_mode.h>
+
+#include <context.h>
+#include <dsp.h>
+#include <utils.h>
+#include <mode.h>
+#include <pi.h>
+#include <intelpci.h>
+#include "drm_emgd_private.h"
+
+#include <tnc/regs.h>
+
+#include <tnc/igd_tnc_wa.h> /* needed for vbios for register defines */
+
+#ifdef CONFIG_DEBUG
+#define FLAG(a) a
+/* Debug flag to turn off CDVO reset sequence */
+static int flag_enable_cdvo_reset = 1;
+#else
+/* Turn all workaround for release driver */
+#define FLAG(a) 1
+#endif
+
+extern unsigned long get_port_type(int crtc_id);
+static void wait_dpll(void);
+
+int program_cdvo_tnc(void);
+static int kms_program_cdvo(emgd_crtc_t *emgd_crtc);
+
+static cdvo_regs_t cdvo_reset[] = {
+           /*turn off the SDVO port*/
+           {0x61140, 0},
+           /*turn off the stall register*/
+           {0x6102C, 0},
+           /*disable SDVO*/
+           {0x61170, 0},
+           /*programmable cdvo stall*/
+           {0x6102c, 0xf},
+           {0x7000, 0x40},
+           /*reset*/
+           {0x7000, 0x51},
+           {0x7000, 0x50},
+           /*High*/
+           {0x7014, 0x00004800},
+           /*strobe data tuning default*/
+           {0x700c, 0x000BB4FF},
+           /*enable sdvo*/
+           {0x61170, 0x20022160},
+           {0x7010, 0x06000200},
+           /* -- Begin Sequence of 3 pixel signal --*/
+           /*Low*/
+           {0x700c, 0x00008000},
+           {0x700c, 0x0008B400},
+           /*High*/
+           {0x700c, 0x0008B4FF},
+           /*Low*/
+           {0x700c, 0x00008000},
+           {0x700c, 0x0008B400},
+           /*High*/
+           {0x700c, 0x0008B4FF},
+           /*Low*/
+           {0x700c, 0x00008000},
+           {0x700c, 0x0008B400},
+           /*High*/
+           {0x700c, 0x0008B4FF},
+           /*Low*/
+           {0x700c, 0x00008000},
+           {0x700c, 0x0008B400},
+           /*High*/
+           {0x700c, 0x0008B4FF},
+           /*Low*/
+           {0x700c, 0x00008000},
+           {0x700c, 0x0008B400},
+           /*High*/
+           {0x700c, 0x0008B4FF},
+           /*Low*/
+           {0x700c, 0x00008000},
+           {0x700c, 0x0008B400},
+           /*High*/
+           {0x700c, 0x0008B4FF},
+           /*reset*/
+           {0x7000, 0x51},
+           {0x7000, 0x50},
+           /*High*/
+           {0x7014, 0x00004800},
+           /*strobe data tuning default*/
+           {0x700c, 0x000BB4FF},
+           /*enable sdvo*/
+           {0x61170, 0x20022160},
+           {0x7010, 0x06000200},
+           /* -- Begin Sequence of 3 pixel signal --*/
+           /*Low*/
+           {0x700c, 0x00008000},
+           {0x700c, 0x0008B400},
+           /*High*/
+           {0x700c, 0x0008B4FF},
+           /*Low*/
+           {0x700c, 0x00008000},
+           {0x700c, 0x0008B400},
+           /*High*/
+           {0x700c, 0x0008B4FF},
+           /*Low*/
+           {0x700c, 0x00008000},
+           {0x700c, 0x0008B400},
+           /*High*/
+           {0x700c, 0x0008B4FF},
+           /*Low*/
+           {0x700c, 0x00008000},
+           {0x700c, 0x0008B400},
+           /*High*/
+           {0x700c, 0x0008B4FF},
+           /*Low*/
+           {0x700c, 0x00008000},
+           {0x700c, 0x0008B400},
+           /*High*/
+           {0x700c, 0x0008B4FF},
+           /*Low*/
+           {0x700c, 0x00008000},
+           {0x700c, 0x0008B400},
+           /*High*/
+           {0x700c, 0x0008B4FF},
+           /*Reset*/
+           {0x7000, 0x51},
+           {0x7000, 0x50},
+           {0x7010, 0x02000200},    /*gtl gtl*/
+           {0x7014, 0x00004000},    /*ODT*/
+           {0x61170, 0x20022160},    /*enable SDVO*/
+           {0x7010, 0x02000200},    /*gtl gtl*/
+           {0x7014, 0x00000800},
+           {0x7014, 0x00004800},    /*rcomp*/
+           {0x7014, 0x00000000},
+           {0x7000, 0x40},            /*enable cdvo*/
+           {0x7000, 0x50},            /*enable cdvo*/
+           {0x7014, 0x00004000},    /*ODT*/
+           {0x61170, 0x20022160},    /*enable SDVO*/
+           {0,0}
+};
+
+
+
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/* Enable this if calculated values are wrong and required fixed table */
+#define CONFIG_FIXED_TABLE  0
+
+#ifdef CONFIG_TNC
+
+extern int program_clock_sdvo_tnc(igd_display_context_t *display,
+	igd_clock_t *clock, unsigned long dclk);
+
+/*===========================================================================
+; File Global Data
+;--------------------------------------------------------------------------*/
+#if CONFIG_FIXED_TABLE
+typedef struct _fixed_clock {
+	unsigned long dclk;
+	unsigned long n;
+	unsigned long m;
+	unsigned long p1;
+} fixed_clock_t;
+
+/* set mmio register required values */
+static fixed_clock_t lvds_fixed_clock_table[] =  {
+	/* Clock       N     M     P1 */
+	{ 65000,      0x01, 0x00, 0x00 },
+	{ 0xffffffff, 0x01, 0x00, 0x00}
+};
+
+/* set mmio register required values */
+static fixed_clock_t sdvo_fixed_clock_table[] =  {
+	/* Clock       N     M    P1 */
+	{ 65000,      0x00, 0x00, 0x00 },
+	{ 0xffffffff, 0x00, 0x00, 0x00}
+};
+#endif
+
+#define LVDS_M_MIN 10
+
+/* This table is also used by mode_tnc.c */
+const unsigned long lvds_m_converts[] = {
+	0x2B, 0x15, 0x2A, 0x35, 0x1A, 0x0D, 0x26, 0x33, 0x19, 0x2C,
+	0x36, 0x3B, 0x1D, 0x2E, 0x37, 0x1B, 0x2D, 0x16, 0x0B, 0x25,
+	0x12, 0x09, 0x24, 0x32, 0x39, 0x1c,
+};
+
+const unsigned long LVDS_M_CONVERTS_LEN=26;   /* Length of the array above*/
+
+#define TARGET_ERROR 46
+
+typedef const struct _tnc_limits {
+	unsigned long ref_freq;
+	unsigned long min_m;
+	unsigned long max_m;
+
+	unsigned long min_n;
+	unsigned long max_n;
+
+	unsigned long min_p1;
+	unsigned long max_p1;
+
+	unsigned long min_p2;
+	unsigned long max_p2;
+
+	unsigned long min_vco;
+	unsigned long max_vco;
+} tnc_limits_t;
+
+/* m, n, p value limits:
+ * source: http://moss.amr.ith.intel.com/sites/LCD/LNC/HAS/Secured
+ * %20Documents/LNC%20HAS%20work%20area/Lincroft%20DPLL_1.2_ww31_08.docx
+ *
+ * Note:
+ * VCO range for 100L is not given: so put a range big enough to go through
+ * calculations for the for loop.
+ */
+static tnc_limits_t tnc_lvds_limits[] =
+{
+	/* reffreq  m      n     p1     p2          vco */
+	{ 200000, 10, 17, 1, 1, 2, 8, 14, 14, 2000000, 3400000},  /* SKU 100 */
+	{ 100000, 20, 34, 1, 1, 2, 8, 14, 14, 1000000, 3400000},  /* SKU 100L */
+	{ 166000, 12, 20, 1, 1, 2, 7, 14, 14, 2000000, 3333333},  /* SKU 83 */
+};
+
+static tnc_limits_t tnc_sdvo_limits[] =
+{
+	/* reffreq  m      n     p1     p2          vco */
+	{  96000, 80,137, 3, 7, 1, 2, 10, 10, 1400000, 2800000},  /* SDVO */
+};
+
+/*!
+ *
+ * @param dclk
+ * @param ref_freq
+ * @param limits
+ * @param m
+ * @param n
+ * @param p
+ * @param target_error
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int calculate_clock(unsigned long dclk,
+	unsigned long ref_freq,
+	tnc_limits_t *l,
+	unsigned long *m,
+	unsigned long *n,
+	unsigned long *p1,
+	unsigned long target_error,
+	unsigned long *actual_dclk,
+	unsigned long port_type,
+	unsigned long pd_type)
+{
+	unsigned long  pdiv;
+	unsigned long  target_vco, actual_freq;
+	long freq_error, min_error;
+	unsigned long dclk_10000;
+
+	unsigned long current_m, current_n, current_p1;
+
+	EMGD_TRACE_ENTER;
+
+	min_error = 100000;
+
+	*m = 0;
+	*n = 0;
+	*p1 = 0;
+
+	/* dclk * 10000, so it does not have to be calculated within the
+	 * loop */
+	dclk_10000 = dclk * 10000;
+
+	for(current_m = l->min_m; current_m <= l->max_m; current_m++) {
+		for(current_n = l->min_n; current_n <= l->max_n; current_n++) {
+			for(current_p1 = l->min_p1; current_p1 <= l->max_p1; current_p1++) {
+
+				/* For both LVDS/SDVO ports min_p2 and max_p2 are same,
+				 * so assign use either min/max p2 */
+				pdiv = current_p1 * l->min_p2;
+				target_vco = dclk * pdiv;
+
+				if (target_vco > l->max_vco) {
+					/* target_vco continues to increase, so start with
+					 * next current_n */
+					break;
+				}
+
+				if (target_vco >= l->min_vco) {
+					/* Frequency calculations for SDVO and LVDS are different
+					 * SDVO Dotclock_frequency = (Reference Frequency * (M+2)) / (N*(P1*P2))
+					 * LVDS DotClk_Frequency = (ReferenceFrequency * M)/ (P1* P2)
+					 * need to find a way to differentiate SDVO and LVDS
+					 * Works for now but signal generated will be different */
+					actual_freq = (ref_freq * current_m) / (current_n*pdiv);
+					freq_error = 10000 - (dclk_10000 / actual_freq);
+
+					if (freq_error < -min_error) {
+						/* freq_error continues to decrease once this
+						 * point is reached, so start with next
+						 * current_n */
+						break;
+					}
+
+					if (freq_error < 0) {
+						freq_error = -freq_error;
+					}
+					if (freq_error < min_error)  {
+						*n = current_n;
+						*m = current_m;
+						*p1 = current_p1;
+						min_error = freq_error;
+						*actual_dclk = actual_freq;
+					}
+				}
+			}
+		}
+		if (min_error == 0) {
+			break;
+		}
+	}
+
+	if (pd_type == PD_DISPLAY_TVOUT) {
+		EMGD_TRACE_EXIT;
+		return 0;
+	}
+	/*
+	 * No clock found that meets error requirement
+	 */
+	if (min_error > (long)target_error) {
+		EMGD_TRACE_EXIT;
+		return 1;
+	}
+
+	EMGD_DEBUG("dclk = (ref*m)/(n*p1*p2) => %lu = (%lu*%lu)/(%lu*%lu*%lu) = %lu",
+		dclk, ref_freq, *m, *n, *p1, l->min_p2,
+		(ref_freq*(*m))/((*n)*(*p1)*l->min_p2));
+	EMGD_DEBUG("min_error:%ld", min_error);
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ *
+ * @param dclk
+ * @param ref_freq
+ * @param limits
+ * @param m
+ * @param n
+ * @param p
+ * @param target_error
+ * @param port_type
+ * @param pd_type
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int get_clock(unsigned long dclk,
+	unsigned long ref_freq,
+	tnc_limits_t *l,
+	unsigned long *m,
+	unsigned long *n,
+	unsigned long *p1,
+	unsigned long target_error,
+	unsigned long port_type,
+	unsigned long *actual_dclk,
+	unsigned long pd_type)
+{
+
+#if CONFIG_FIXED_TABLE
+	fixed_clock_t *fixed;
+	EMGD_TRACE_ENTER;
+    /* Enable this if calculated values are wrong and required fixed table */
+	if (port_type == IGD_PORT_LVDS) {
+		fixed = lvds_fixed_clock_table;
+	} else {
+		fixed = sdvo_fixed_clock_table;
+	}
+
+	/* First check for a fixed clock from the table. These are ones that
+	 * can't be calculated correctly. */
+	while (fixed->dclk != 0xffffffff) {
+		if (fixed->dclk == dclk) {
+			EMGD_DEBUG("Using Fixed Clock From table for clock %ld", dclk);
+			*m = fixed->m;
+			*n = fixed->n;
+			*p1 = fixed->p1;
+			EMGD_TRACE_EXIT;
+			return 0;
+		}
+		fixed++;
+	}
+#endif
+
+	EMGD_TRACE_ENTER;
+	/* No fixed clock found so calculate one. */
+	EMGD_DEBUG("Calculating dynamic clock for clock %ld", dclk);
+
+	if (calculate_clock(dclk, ref_freq, l, m, n, p1, target_error, actual_dclk, port_type, pd_type)) {
+		/* No usable clock.  Cannot use 640x480 at 60 as default, because
+		 * there are several vcos and several reference clocks. */
+		EMGD_ERROR("Could not calculate clock %ld, returning default.", dclk);
+		EMGD_TRACE_EXIT;
+		return 1;
+	}
+
+	if (pd_type == PD_DISPLAY_TVOUT) {
+		*p1 = 2;
+		*m = 100;
+		*n = 5;
+	}
+
+	/* Translate returned values to m,n,p1 register values */
+	/* No change required for *n value */
+	if (port_type == IGD_PORT_SDVO) {
+		*p1 = (1L << (*p1 - 1));
+		*m -= 2;
+		*n = (1L << (*n -1));
+	} else {
+		*p1 = (1L << (*p1 - 2));
+		*m = lvds_m_converts[*m - LVDS_M_MIN];
+	}
+
+	EMGD_DEBUG("reg m=%lu n=%lu p1=%lu p2=%lu", *m, *n, *p1, l->min_p2);
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ *
+ * @param emgd_crtc
+ * @param clock
+ * @param dclk
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int kms_program_clock_lvds_tnc(emgd_crtc_t *emgd_crtc,
+	igd_clock_t *clock,
+	unsigned long dclk)
+{
+	struct drm_device  *dev = NULL;
+	igd_display_pipe_t *pipe = NULL;
+	igd_context_t      *context = NULL;
+	igd_display_port_t *port = NULL;
+	struct drm_encoder *encoder = NULL;
+	emgd_encoder_t     *emgd_encoder = NULL;
+	unsigned long pt;
+	int ret;
+	unsigned long m, n, p1;
+	unsigned long control;
+	unsigned long ref_freq;
+	tnc_limits_t *l = NULL;
+	unsigned long count;
+
+	EMGD_TRACE_ENTER;
+
+	pipe = emgd_crtc->igd_pipe;
+	dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+	pt = get_port_type(emgd_crtc->crtc_id);
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (((struct drm_crtc *)(&emgd_crtc->base)) == encoder->crtc) {
+			emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+			port = emgd_encoder->igd_port;
+			break;
+		}
+	}
+
+
+	/* LNC ref_freq is determined by SKU, convert to KHz */
+#if 0
+	ref_freq = display->context->device_context.gfx_freq * 1000L;
+#else
+	ref_freq = context->device_context.core_freq;
+	ref_freq = ref_freq * 1000;
+#endif
+
+#if 0
+	/* Find m,n,p,vco limits */
+	if (ref_freq == 200000) {
+		l = &tnc_lvds_limits[0];
+	} else if (ref_freq == 100000) {
+		l = &tnc_lvds_limits[1];
+	} else if (ref_freq == 166000) {
+		l = &tnc_lvds_limits[2];
+	}
+#endif
+
+	for(count=0; count<3; count++){
+		if (tnc_lvds_limits[count].ref_freq == ref_freq){
+			l = &tnc_lvds_limits[count];
+			break;
+		}
+	}
+
+/* PO Debug */
+#if 0
+	/* WRITE_PORT80(0xED); */
+
+	if(ref_freq == 166000){
+	WRITE_PORT80(0xEF);
+	}
+
+	if (!l){
+		/* FATAL ERROR */
+		DEAD_LOOP(0xDD);
+	}
+#endif
+
+	/* Per UMG, there is no defined target_error for LVDS, it supposed to
+	 * work for all expected dclks. */
+#if 1
+	if (port) {
+		ret = get_clock(dclk, ref_freq, l, &m, &n, &p1, dclk /* target_error */,
+			port->port_type, &clock->actual_dclk, port->pd_driver->type);
+	} else {
+		ret = 1;
+	}
+	if (ret) {
+		EMGD_ERROR_EXIT("Clock %ld could not be programmed", dclk);
+		/* DEAD_LOOP(0xFF); */
+		return ret;
+	}
+#else
+	/* Hard code the values for now */
+	m = 0x2D;  // ITP uses 0x2E, should change
+	p1 = 2;
+
+#endif
+
+#if 0
+	/* If clocks are already running at required clocks, just return */
+	if (PIPE(display)->dclk == dclk) {
+		return 0;
+	}
+#endif
+
+	/* Disable DPLL */
+#if 0
+	control = BIT28 | (1<<clock->p_shift); //Why are we shifting 1 to P1, GMA carry over???
+#else
+	control = BIT28;
+#endif
+	EMGD_WRITE32(control, context->device_context.virt_mmadr + clock->dpll_control);
+	EMGD_DEBUG("lvds: EMGD_WRITE32: 0x%lx = 0x%lx",
+		clock->dpll_control, control);
+
+	/* Program M */
+	EMGD_WRITE32((m<<8), context->device_context.virt_mmadr + clock->mnp);
+
+	EMGD_WRITE32((m<<8), context->device_context.virt_mmadr + 0xF044); //BUGBUG
+
+	EMGD_DEBUG("lvds: EMGD_WRITE32: 0x%lx = 0x%lx",
+		clock->mnp, (m<<8));
+
+	/* Enable DPLL */
+	control = (BIT31 | BIT28 | BIT27) | (p1<<clock->p_shift);
+
+/* PO Debug..*/
+#if 0
+	/* set VCO select */
+	if (ref_freq == 166000) {
+		control |= BIT16;
+	}
+#endif
+
+
+	EMGD_WRITE32(control, context->device_context.virt_mmadr + clock->dpll_control);
+	EMGD_DEBUG("lvds: EMGD_WRITE32: 0x%lx = 0x%lx",
+		clock->dpll_control, control);
+
+	/* Wait 150us for the DPLL to stabilize */
+	OS_SLEEP(150);
+	pipe->dclk = dclk;
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+/*!
+ *
+ * @param display
+ * @param clock
+ * @param dclk
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int program_clock_lvds_tnc(igd_display_context_t *display,
+	igd_clock_t *clock,
+	unsigned long dclk)
+{
+	int ret;
+	unsigned long m, n, p1;
+	unsigned long control;
+	unsigned long ref_freq;
+	igd_display_port_t *port;
+	tnc_limits_t *l = NULL;
+	unsigned long count;
+
+	EMGD_TRACE_ENTER;
+
+	port = PORT_OWNER(display);
+
+	/* LNC ref_freq is determined by SKU, convert to KHz */
+#if 0
+	ref_freq = display->context->device_context.gfx_freq * 1000L;
+#else
+	ref_freq = display->context->device_context.core_freq;
+	ref_freq = ref_freq * 1000;
+#endif
+
+#if 0
+	/* Find m,n,p,vco limits */
+	if (ref_freq == 200000) {
+		l = &tnc_lvds_limits[0];
+	} else if (ref_freq == 100000) {
+		l = &tnc_lvds_limits[1];
+	} else if (ref_freq == 166000) {
+		l = &tnc_lvds_limits[2];
+	}
+#endif
+
+	for(count=0; count<3; count++){
+		if (tnc_lvds_limits[count].ref_freq == ref_freq){
+			l = &tnc_lvds_limits[count];
+			break;
+		}
+	}
+
+/* PO Debug */
+#if 0
+	/* WRITE_PORT80(0xED); */
+
+	if(ref_freq == 166000){
+	WRITE_PORT80(0xEF);
+	}
+
+	if (!l){
+		/* FATAL ERROR */
+		DEAD_LOOP(0xDD);
+	}
+#endif
+
+	/* Per UMG, there is no defined target_error for LVDS, it supposed to
+	 * work for all expected dclks. */
+#if 1
+	ret = get_clock(dclk, ref_freq, l, &m, &n, &p1, dclk /* target_error */,
+		port->port_type, &clock->actual_dclk, port->pd_driver->type);
+	if (ret) {
+		EMGD_ERROR_EXIT("Clock %ld could not be programmed", dclk);
+		/* DEAD_LOOP(0xFF); */
+		return ret;
+	}
+#else
+	/* Hard code the values for now */
+	m = 0x2D;  // ITP uses 0x2E, should change
+	p1 = 2;
+
+#endif
+
+#if 0
+	/* If clocks are already running at required clocks, just return */
+	if (PIPE(display)->dclk == dclk) {
+		return 0;
+	}
+#endif
+
+	/* Disable DPLL */
+#if 0
+	control = BIT28 | (1<<clock->p_shift); //Why are we shifting 1 to P1, GMA carry over???
+#else
+	control = BIT28;
+#endif
+	WRITE_MMIO_REG(display, clock->dpll_control, control);
+	EMGD_DEBUG("lvds: EMGD_WRITE32: 0x%lx = 0x%lx",
+		clock->dpll_control, control);
+
+	/* Program M */
+	WRITE_MMIO_REG(display, clock->mnp, (m<<8));
+
+	WRITE_MMIO_REG(display, 0xF044, (m<<8)); //BUGBUG
+
+	EMGD_DEBUG("lvds: EMGD_WRITE32: 0x%lx = 0x%lx",
+		clock->mnp, (m<<8));
+
+	/* Enable DPLL */
+	control = (BIT31 | BIT28 | BIT27) | (p1<<clock->p_shift);
+
+/* PO Debug..*/
+#if 0
+	/* set VCO select */
+	if (ref_freq == 166000) {
+		control |= BIT16;
+	}
+#endif
+
+
+	WRITE_MMIO_REG(display, clock->dpll_control, control);
+	EMGD_DEBUG("lvds: EMGD_WRITE32: 0x%lx = 0x%lx",
+		clock->dpll_control, control);
+
+	/* Wait 150us for the DPLL to stabilize */
+	OS_SLEEP(150);
+	PIPE(display)->dclk = dclk;
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*!
+ *
+ * @param emgd_crtc
+ * @param clock
+ * @param dclk
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int kms_program_clock_sdvo_tnc(emgd_crtc_t *emgd_crtc,
+	igd_clock_t *clock,
+	unsigned long dclk)
+{
+	struct drm_device  *dev          = NULL;
+	igd_display_pipe_t *pipe         = NULL;
+	igd_context_t      *context      = NULL;
+	igd_display_port_t *port         = NULL;
+	struct drm_encoder *encoder      = NULL;
+	emgd_encoder_t     *emgd_encoder = NULL;
+	unsigned long pt;
+	int ret;
+	unsigned long m, n, p1;
+	unsigned long control;
+	unsigned long ref_freq;
+	unsigned long port_mult, vga_mult;
+	unsigned long target_error, actual_dclk;
+	tnc_limits_t *l;
+
+	EMGD_DEBUG("Enter program_clock");
+
+	pipe = emgd_crtc->igd_pipe;
+	dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+	pt = get_port_type(emgd_crtc->crtc_id);
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (((struct drm_crtc *)(&emgd_crtc->base)) == encoder->crtc) {
+			emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+			port = emgd_encoder->igd_port;
+			break;
+		}
+	}
+	if (!port) {
+		EMGD_ERROR_EXIT("No port");
+		return -1;
+	}
+
+	/* FIXME: No info available in EAS and waiting for info. */
+	if (dclk > 100000) {          /* 100-200 MHz */
+		port_mult = 1;
+	} else if (dclk > 50000) {    /* 50-100 Mhz */
+		port_mult = 2;
+	} else {                      /* 25-50 Mhz */
+		port_mult = 4;
+	}
+
+	dclk *= port_mult;
+
+	l = &tnc_sdvo_limits[0];
+	ref_freq = l->ref_freq;
+
+	vga_mult = READ_MMIO_REG_TNC(IGD_PORT_SDVO, clock->dpll_control) & 0x3;
+
+	target_error = TARGET_ERROR;
+
+	/* For external clock sources always use ref_clock == dclk */
+	if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+		ref_freq = dclk;
+		/* When clock source sdvo device, allowed error is 0. */
+		target_error = 0;
+	}
+
+	if (port) {
+		ret = get_clock(dclk, ref_freq, l, &m, &n, &p1, target_error,
+			IGD_PORT_SDVO, &actual_dclk, port->pd_driver->type);
+	} else {
+		ret = 1;
+	}
+
+	clock->actual_dclk = actual_dclk/port_mult;
+
+	if (ret) {
+		EMGD_ERROR("Clock %ld could not be programmed", dclk);
+		return ret;
+	}
+
+	/* Disable DPLL, Write 2 into P for saftey */
+	control = BIT28 | (2<<clock->p_shift) | vga_mult;
+
+	WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, clock->dpll_control, control);
+	EMGD_DEBUG("sdvo: EMGD_WRITE32: 0x%lx = 0x%lx",
+		clock->dpll_control, control);
+
+	/* Program N, M */
+	WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, clock->mnp, (n<<16) | m);
+	EMGD_DEBUG("sdvo: EMGD_WRITE32: 0x%lx = 0x%lx",
+		clock->mnp, (n<<16)|m);
+
+	/* Enable DPLL, Disable VGA mode and sitck in new P values */
+	control = BIT31 | BIT30 | BIT28 | (p1<<clock->p_shift) | vga_mult;
+
+	/* Set the clock source correctly based on PD settings */
+	if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+		control |= port->clock_bits;
+	}
+
+	/* sDVO Multiplier bits[7:0] */
+	if (port_mult == 2) {
+		control |= (1 << 4);
+	} else if (port_mult == 3) {
+		control |= (2 << 4);
+	} else if (port_mult == 4) {
+		control |= (3 << 4);
+	}
+
+	/* Double buffered */
+	WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, clock->dpll_control, control);
+	WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, clock->dpll_control, control);
+	EMGD_DEBUG("sdvo: EMGD_WRITE32: 0x%lx = 0x%lx",
+		clock->dpll_control, control);
+
+	/* We must wait for 150 us for the dpll clock to warm up */
+	//OS_SLEEP(150);
+	wait_dpll();
+
+	kms_program_cdvo(emgd_crtc);
+
+	return 0;
+}
+/*!
+ *
+ * @param display
+ * @param clock
+ * @param dclk
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int program_clock_sdvo_tnc(igd_display_context_t *display,
+	igd_clock_t *clock,
+	unsigned long dclk)
+{
+	int ret;
+	unsigned long m, n, p1;
+	unsigned long control;
+	unsigned long ref_freq;
+	unsigned long port_mult, vga_mult;
+	unsigned long target_error, actual_dclk;
+	igd_display_port_t *port;
+	tnc_limits_t *l;
+
+	EMGD_DEBUG("Enter program_clock");
+
+	port = PORT_OWNER(display);
+
+	/* FIXME: No info available in EAS and waiting for info. */
+	if (dclk > 100000) {          /* 100-200 MHz */
+		port_mult = 1;
+	} else if (dclk > 50000) {    /* 50-100 Mhz */
+		port_mult = 2;
+	} else {                      /* 25-50 Mhz */
+		port_mult = 4;
+	}
+
+	dclk *= port_mult;
+
+	l = &tnc_sdvo_limits[0];
+	ref_freq = l->ref_freq;
+
+	vga_mult = READ_MMIO_REG_TNC(IGD_PORT_SDVO, clock->dpll_control) & 0x3;
+
+	target_error = TARGET_ERROR;
+
+	/* For external clock sources always use ref_clock == dclk */
+	if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+		ref_freq = dclk;
+		/* When clock source sdvo device, allowed error is 0. */
+		target_error = 0;
+	}
+
+	ret = get_clock(dclk, ref_freq, l, &m, &n, &p1, target_error,
+		IGD_PORT_SDVO, &actual_dclk, port->pd_driver->type);
+
+	clock->actual_dclk = actual_dclk/port_mult;
+
+	if (ret) {
+		EMGD_ERROR("Clock %ld could not be programmed", dclk);
+		return ret;
+	}
+
+	/* Disable DPLL, Write 2 into P for saftey */
+	control = BIT28 | (2<<clock->p_shift) | vga_mult;
+
+	WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, clock->dpll_control, control);
+	EMGD_DEBUG("sdvo: EMGD_WRITE32: 0x%lx = 0x%lx",
+		clock->dpll_control, control);
+
+	/* Program N, M */
+	WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, clock->mnp, (n<<16) | m);
+	EMGD_DEBUG("sdvo: EMGD_WRITE32: 0x%lx = 0x%lx",
+		clock->mnp, (n<<16)|m);
+
+	/* Enable DPLL, Disable VGA mode and sitck in new P values */
+	control = BIT31 | BIT30 | BIT28 | (p1<<clock->p_shift) | vga_mult;
+
+	/* Set the clock source correctly based on PD settings */
+	if(port->pd_flags & PD_FLAG_CLK_SOURCE) {
+		control |= port->clock_bits;
+	}
+
+	/* sDVO Multiplier bits[7:0] */
+	if (port_mult == 2) {
+		control |= (1 << 4);
+	} else if (port_mult == 3) {
+		control |= (2 << 4);
+	} else if (port_mult == 4) {
+		control |= (3 << 4);
+	}
+
+	/* Double buffered */
+	WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, clock->dpll_control, control);
+	WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, clock->dpll_control, control);
+	EMGD_DEBUG("sdvo: EMGD_WRITE32: 0x%lx = 0x%lx",
+		clock->dpll_control, control);
+
+	/* We must wait for 150 us for the dpll clock to warm up */
+	//OS_SLEEP(150);
+	wait_dpll();
+
+	program_cdvo_tnc();
+
+	return 0;
+}
+
+int kms_program_clock_tnc(emgd_crtc_t *emgd_crtc,
+	igd_clock_t *clock,
+	unsigned long dclk)
+{
+	EMGD_TRACE_ENTER;
+
+	if (get_port_type(emgd_crtc->crtc_id) == IGD_PORT_LVDS) {
+		EMGD_TRACE_EXIT;
+		return kms_program_clock_lvds_tnc(emgd_crtc, clock, dclk);
+	} else {
+		EMGD_TRACE_EXIT;
+		return kms_program_clock_sdvo_tnc(emgd_crtc, clock, dclk);
+	}
+}
+
+int program_clock_tnc(igd_display_context_t *display,
+	igd_clock_t *clock,
+	unsigned long dclk)
+{
+	EMGD_TRACE_ENTER;
+
+	if (PORT_TYPE(display) == IGD_PORT_LVDS) {
+		EMGD_TRACE_EXIT;
+		return program_clock_lvds_tnc(display, clock, dclk);
+	} else {
+		EMGD_TRACE_EXIT;
+		return program_clock_sdvo_tnc(display, clock, dclk);
+	}
+}
+
+
+/*!
+ * Poll for DPLL register lock. This is only valid for DPLLB
+ *
+ * @return void
+ */
+static void wait_dpll(void)
+{
+#ifndef CONFIG_MICRO
+	unsigned long temp;
+	os_alarm_t timeout;
+
+	EMGD_TRACE_ENTER;
+
+	/* Wait for DPLL lock, about 50 msec (20Hz). */
+	timeout = OS_SET_ALARM(50);
+	do {
+		OS_SCHEDULE();
+		/* Check for Bit16, 1 means DPLL is locked (TNC EAS Ver 2.0) */
+		temp = (READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x606C) & 0x10000) >> 16;
+
+		/* Check for timeout */
+	} while ((!temp) && (!OS_TEST_ALARM(timeout)));
+
+	if (!temp) {
+		EMGD_ERROR_EXIT("Timeout waiting for pipe enable/disable");
+	}
+
+	EMGD_TRACE_EXIT;
+#else
+	/* to save space in VBIOS, we use to old method of waiting for the DPLL
+	* to warm up */
+	OS_SLEEP(150);
+#endif
+	return;
+}
+
+
+/* This is the initialization code for B0 stepping */
+static int kms_program_cdvo(emgd_crtc_t *emgd_crtc)
+{
+	int counter = 0;
+	igd_display_pipe_t *pipe = NULL;
+
+	EMGD_TRACE_ENTER;
+
+	pipe = emgd_crtc->igd_pipe;
+
+    #ifndef CONFIG_MICRO
+	/*
+	 * CDVO reset has been done. Check that offset 0x7000 has the value 0x50
+	 * and this would mean that reset has been done. We only need to do cdvo
+	 * reset once per warm reset
+	 */
+	if((READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000) == 0x50) ||
+		!FLAG(flag_enable_cdvo_reset)){
+		EMGD_TRACE_EXIT;
+		return TRUE;
+	}
+
+    #endif
+
+	/* pipe_temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, PIPE(display)->pipe_reg); */
+
+	/* Disable pipe */
+	WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, pipe->pipe_reg, 0);
+	WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, pipe->pipe_reg, 0);
+
+	/* Sleep for a while to wait for the pipe to disable. There are no
+	* status bits to check if pipe B has been enable */
+	OS_SLEEP(25);
+
+    #if 0
+       /* Disable DPLL */
+       vga_mult = READ_MMIO_REG_TNC(IGD_PORT_SDVO,
+           PIPE(display)->clock_reg->dpll_control) & 0x3;
+       control = BIT28 | (2<<PIPE(display)->clock_reg->p_shift) | vga_mult;
+
+       WRITE_MMIO_REG_TNC(IGD_PORT_SDVO,
+           PIPE(display)->clock_reg->dpll_control, control);
+       WRITE_MMIO_REG_TNC(IGD_PORT_SDVO,
+           PIPE(display)->clock_reg->dpll_control, control);
+    #endif
+
+	/* the checking is needed for VBIOS but not needed for driver */
+	do{
+		WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, cdvo_reset[counter].reg,
+			cdvo_reset[counter].value);
+			counter++;
+	}while(cdvo_reset[counter].reg != 0);
+
+	/* Enable sDVOB port */
+	WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x61140,
+	READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x61140) | 0xC0000018 );
+
+
+	EMGD_TRACE_EXIT;
+
+	return TRUE;
+}
+
+/* This is the initialization code for B0 stepping */
+int program_cdvo_tnc(void)
+{
+	int 		  counter = 0;
+	unsigned long pipe_temp;
+
+	EMGD_TRACE_ENTER;
+
+    #ifndef CONFIG_MICRO
+	/*
+	 * CDVO reset has been done. Check that offset 0x7000 has the value 0x50
+	 * and this would mean that reset has been done. We only need to do cdvo
+	 * reset once per warm reset
+	 */
+	if((READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x7000) == 0x50) ||
+		!FLAG(flag_enable_cdvo_reset)){
+		EMGD_TRACE_EXIT;
+		return TRUE;
+	}
+
+    #endif
+
+	pipe_temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, PIPEB_CONF);
+
+	/* Disable pipe */
+	WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PIPEB_CONF, 0);
+	WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, PIPEB_CONF, 0);
+
+	/* Sleep for a while to wait for the pipe to disable. There are no
+	* status bits to check if pipe B has been enable */
+	OS_SLEEP(25);
+
+#if 0
+       /* Disable DPLL */
+       vga_mult = READ_MMIO_REG_TNC(IGD_PORT_SDVO,
+           PIPE(display)->clock_reg->dpll_control) & 0x3;
+       control = BIT28 | (2<<PIPE(display)->clock_reg->p_shift) | vga_mult;
+
+       WRITE_MMIO_REG_TNC(IGD_PORT_SDVO,
+           PIPE(display)->clock_reg->dpll_control, control);
+       WRITE_MMIO_REG_TNC(IGD_PORT_SDVO,
+           PIPE(display)->clock_reg->dpll_control, control);
+#endif
+
+	/* the checking is needed for VBIOS but not needed for driver */
+	do{
+		WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, cdvo_reset[counter].reg,
+			cdvo_reset[counter].value);
+			counter++;
+	}while(cdvo_reset[counter].reg != 0);
+
+	/* Enable sDVOB port */
+	WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, 0x61140,
+	READ_MMIO_REG_TNC(IGD_PORT_SDVO, 0x61140) | 0xC0000018 );
+
+	/* Restore Pipe B configuration value */
+	WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PIPEB_CONF, pipe_temp);
+	WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, PIPEB_CONF, pipe_temp);
+
+	EMGD_TRACE_EXIT;
+
+	return TRUE;
+}
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/mode/tnc/kms_mode_tnc.c b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/kms_mode_tnc.c
new file mode 100644
index 0000000..30696ac
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/kms_mode_tnc.c
@@ -0,0 +1,1746 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: kms_mode_tnc.c
+ * $Revision: 1.5 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2011, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+#include <igd_pwr.h>
+#include <utils.h>
+#include <vga.h>
+#include <pi.h>
+
+#include <tnc/regs.h>
+#include <tnc/context.h>
+#include <tnc/mi.h>
+#include <tnc/instr.h>
+#include <tnc/igd_tnc_wa.h>
+#include "drm_emgd_private.h"
+
+#include "../cmn/mode_dispatch.h"
+#include "../cmn/match.h"
+#include "mode_tnc.h"
+#include <math_fix.h>
+#include <memory.h>
+
+
+/*------------------------------------------------------------------------------
+ * Function Prototypes
+ *----------------------------------------------------------------------------*/
+int kms_mode_get_stride_stereo_tnc(igd_display_pipe_t *pipe,
+	igd_display_plane_t *plane,
+	unsigned long *stride,
+	unsigned long *stereo,
+	unsigned long flags);
+void kms_program_pipe_vga_tnc(emgd_crtc_t *emgd_crtc);
+static void kms_program_pipe_tnc(emgd_crtc_t *emgd_crtc);
+static void kms_set_pipe_pwr_tnc(emgd_crtc_t *emgd_crtc, unsigned long enable);
+static void kms_program_plane_tnc(emgd_crtc_t *emgd_crtc, unsigned long status);
+static void kms_set_plane_pwr_tnc(emgd_crtc_t *emgd_crtc, unsigned long enable);
+static int  kms_program_port_tnc(emgd_encoder_t *emgd_encoder,
+	unsigned long status);
+static int  kms_program_port_lvds_tnc(emgd_encoder_t *emgd_encoder,
+	unsigned long status);
+static int  kms_program_port_sdvo_tnc(emgd_encoder_t *emgd_encoder,
+	unsigned long status);
+static int  kms_post_program_port_tnc(emgd_encoder_t *emgd_encoder,
+	unsigned long status);
+static u32  kms_get_vblank_counter_tnc(emgd_crtc_t *emgd_crtc);
+
+
+static int set_color_correct_tnc(emgd_crtc_t *emgd_crtc);
+
+extern unsigned long get_port_type(int crtc_id);
+extern void wait_pipe(unsigned long pt, unsigned long pipe_reg, unsigned long check_on_off);
+extern void disable_vga_tnc (unsigned char *mmio);
+extern int write_bunit_tnc(unsigned long reg, unsigned long val);
+extern int read_bunit_tnc(unsigned long reg, unsigned long *val);
+extern int kms_program_clock_tnc(emgd_crtc_t *emgd_crtc,
+	igd_clock_t *clock, unsigned long dclk);
+extern int wait_for_vblank_tnc(unsigned long pipe_reg);
+extern void initialize_ST_bridge(igd_context_t *context,
+	igd_display_port_t *port);
+
+
+/*------------------------------------------------------------------------------
+ * Global Variables
+ *----------------------------------------------------------------------------*/
+extern int flag_basic_htotal_formula_wa;
+extern int flag_turn_off_port_wa;
+extern int flag_enable_tuning_wa;
+extern unsigned long ports_tnc[2];
+extern int vphase;
+extern tnc_wa_timing_t tune;
+extern mode_data_tnc_t device_data_tnc[1];
+
+
+/*------------------------------------------------------------------------------
+ * KMS Dispatch Table
+ *----------------------------------------------------------------------------*/
+mode_kms_dispatch_t mode_kms_dispatch_tnc = {
+	kms_program_pipe_tnc,
+	kms_set_pipe_pwr_tnc,
+	kms_program_plane_tnc,
+	kms_set_plane_pwr_tnc,
+	kms_program_port_tnc,
+	kms_post_program_port_tnc,
+	kms_get_vblank_counter_tnc,
+	kms_match_mode,
+};
+
+
+
+/*!
+ * Get the stride and stereo values based on the display.
+ *
+ * @param plane Pointer to hardware device instance data
+ * @param pipe  Pointer to hardware device instance data
+ * @param flags Should the stereo be for the frontbuffer or backbuffer?
+ *
+ * @return stride - Stride of the display
+ * @return stereo - Stereo address of the display
+ */
+int kms_mode_get_stride_stereo_tnc(igd_display_pipe_t *pipe,
+		igd_display_plane_t *plane,
+		unsigned long *stride,
+		unsigned long *stereo,
+		unsigned long flags)
+{
+	unsigned long pitch = plane->fb_info->screen_pitch;
+	igd_timing_info_t *timing = pipe->timing;
+	unsigned long base_offset;
+
+	EMGD_TRACE_ENTER;
+
+	base_offset = plane->fb_info->visible_offset;
+	*stride = pitch;
+	*stereo = 0;
+
+	/* For field replication, valid for interlaced modes only
+	 *     set stereo = fb_base
+	 *         stride = pitch
+	 */
+	if (timing->mode_info_flags & IGD_SCAN_INTERLACE) {
+
+		if(timing->mode_info_flags & IGD_LINE_DOUBLE) {
+			/* Interlaced + Line double flags means field replication.
+			 * same lines are sent for both fields. Program the
+			 * second eye to be same as the first
+			 */
+			*stereo = base_offset;
+		} else {
+			/* Regular interlaced. Second eye starts on line 2.
+			 * Skip every other line.
+			 */
+			*stereo = base_offset + pitch;
+			*stride = pitch << 1;
+		}
+	}
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+
+
+/*!
+ *
+ * @param emgd_crtc
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL if color attributes not found
+ */
+static int set_color_correct_tnc(emgd_crtc_t *emgd_crtc)
+{
+	const int        MID_PIXEL_VAL    = 125;
+	const int        MAX_PIXEL_VAL    = 255;
+	const int        NUM_PALETTE_ENTRIES = 256;
+
+	igd_display_port_t *port = NULL;
+	igd_display_pipe_t *pipe = NULL;
+	struct drm_encoder *encoder = NULL;
+	emgd_encoder_t     *emgd_encoder = NULL;
+
+	unsigned int     gamma_r_max_24i_8f, gamma_r_min_24i_8f;
+	unsigned int     gamma_g_max_24i_8f, gamma_g_min_24i_8f;
+	unsigned int     gamma_b_max_24i_8f, gamma_b_min_24i_8f;
+	unsigned int     new_gamma_r_24i_8f, new_gamma_g_24i_8f;
+	unsigned int     new_gamma_b_24i_8f;
+	unsigned int     gamma_normal_r_24i_8f, gamma_normal_g_24i_8f;
+	unsigned int     gamma_normal_b_24i_8f;
+	int              brightness_factor_r, brightness_factor_g;
+	int              brightness_factor_b;
+	int              contrast_factor_r, contrast_factor_g;
+	int              contrast_factor_b;
+
+	unsigned int      *palette;
+	unsigned int       i;
+	struct drm_device *dev = NULL;
+
+	igd_range_attr_t *gamma_attr      = NULL, *contrast_attr = NULL;
+	igd_range_attr_t *brightness_attr = NULL;
+	igd_attr_t       *hal_attr_list   = NULL;
+
+	EMGD_TRACE_ENTER;
+
+	pipe = emgd_crtc->igd_pipe;
+	dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (((struct drm_crtc *)(&emgd_crtc->base)) == encoder->crtc) {
+			emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+			port = emgd_encoder->igd_port;
+			break;
+		}
+	}
+	if (!port) {
+		EMGD_ERROR_EXIT("No port being used.");
+		return -IGD_ERROR_INVAL;
+	}
+	hal_attr_list  = port->attributes;
+
+	/* Using OS_ALLOC to avoid using > 1024 on stack (frame size warning ) */
+	palette = OS_ALLOC(sizeof (unsigned int) * NUM_PALETTE_ENTRIES);
+
+	/* start with a fresh palette */
+	for (i = 0; i < NUM_PALETTE_ENTRIES; i++) {
+		palette[i] = (i << 16) | (i << 8) | i;
+	}
+
+	/* get a pointer to gamma, contrast, and brightness attr */
+	i = 0;
+
+	while (PD_ATTR_LIST_END != hal_attr_list[i].id) {
+		switch (hal_attr_list[i].id) {
+		case PD_ATTR_ID_FB_GAMMA:
+			gamma_attr      = (igd_range_attr_t *) &hal_attr_list[i];
+			break;
+
+		case PD_ATTR_ID_FB_BRIGHTNESS:
+			brightness_attr = (igd_range_attr_t *) &hal_attr_list[i];
+			break;
+
+		case PD_ATTR_ID_FB_CONTRAST:
+			contrast_attr   = (igd_range_attr_t *) &hal_attr_list[i];
+			break;
+
+		default:
+			break;
+		}
+
+		i++;
+	}
+
+	if(!gamma_attr || !brightness_attr || !contrast_attr) {
+		EMGD_ERROR_EXIT("Color Correction Atrributes not found!");
+		return -IGD_ERROR_INVAL;
+	}
+
+	/* Get the max and min */
+	gamma_r_max_24i_8f = ((gamma_attr->max >> 16) & 0xFF) << 3;
+	gamma_g_max_24i_8f = ((gamma_attr->max >>  8) & 0xFF) << 3;
+	gamma_b_max_24i_8f =  (gamma_attr->max        & 0xFF) << 3;
+
+	gamma_r_min_24i_8f = ((gamma_attr->min >> 16) & 0xFF) << 3;
+	gamma_g_min_24i_8f = ((gamma_attr->min >>  8) & 0xFF) << 3;
+	gamma_b_min_24i_8f =  (gamma_attr->min        & 0xFF) << 3;
+
+	/* The new gamma values are in 3i.5f format, but we must convert it
+	 * to 24i.8f format before passing it to OS_POW_FIX
+	 */
+	new_gamma_r_24i_8f = ((gamma_attr->current_value >> 16) & 0xFF) << 3;
+	new_gamma_g_24i_8f = ((gamma_attr->current_value >> 8) & 0xFF) << 3;
+	new_gamma_b_24i_8f = (gamma_attr->current_value & 0xFF) << 3;
+
+	/* make sure the new gamma is within range */
+	new_gamma_r_24i_8f = OS_MIN(gamma_r_max_24i_8f, new_gamma_r_24i_8f);
+	new_gamma_r_24i_8f = OS_MAX(gamma_r_min_24i_8f, new_gamma_r_24i_8f);
+	new_gamma_g_24i_8f = OS_MIN(gamma_g_max_24i_8f, new_gamma_g_24i_8f);
+	new_gamma_g_24i_8f = OS_MAX(gamma_g_min_24i_8f, new_gamma_g_24i_8f);
+	new_gamma_b_24i_8f = OS_MIN(gamma_b_max_24i_8f, new_gamma_b_24i_8f);
+	new_gamma_b_24i_8f = OS_MAX(gamma_b_min_24i_8f, new_gamma_b_24i_8f);
+
+
+	gamma_normal_r_24i_8f =
+		OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_r_24i_8f);
+
+	gamma_normal_g_24i_8f =
+		OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_g_24i_8f);
+
+	gamma_normal_b_24i_8f =
+		OS_POW_FIX(MAX_PIXEL_VAL, (1<<16)/new_gamma_b_24i_8f);
+
+	for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+		unsigned int new_gamma;
+		unsigned int cur_color;
+		unsigned int cur_palette = palette[i];
+
+		/* Note that we do not try to calculate the gamma if it
+		 * is 1.0, e.g. 0x100.  This is to avoid round-off errors
+		 */
+
+		/* red: calculate and make sure the result is within range */
+		if (0x100 != new_gamma_r_24i_8f) {
+			cur_color  = (cur_palette >> 16) & 0xFF;
+			new_gamma  = OS_POW_FIX(cur_color, (1<<16)/new_gamma_r_24i_8f);
+			new_gamma  = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_r_24i_8f;
+			palette[i] &= 0x00FFFF;
+			palette[i] |=
+				(OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF) << 16;
+		}
+
+		/* green: calculate and make sure the result is within range */
+		if (0x100 != new_gamma_g_24i_8f) {
+			cur_color  = (cur_palette >> 8) & 0xFF;
+			new_gamma  = OS_POW_FIX(cur_color, (1<<16)/new_gamma_g_24i_8f);
+			new_gamma  = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_g_24i_8f;
+			palette[i] &= 0xFF00FF;
+			palette[i] |=
+				(OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF) << 8;
+		}
+
+		/* blue: calculate and make sure the result is within range */
+		if (0x100 != new_gamma_b_24i_8f) {
+			cur_color  = cur_palette & 0xFF;
+			new_gamma  = OS_POW_FIX(cur_color, (1<<16)/new_gamma_b_24i_8f);
+			new_gamma  = (MAX_PIXEL_VAL * new_gamma)/gamma_normal_b_24i_8f;
+			palette[i] &= 0xFFFF00;
+			palette[i] |=
+				(OS_MIN(new_gamma, (unsigned) MAX_PIXEL_VAL) & 0xFF);
+		}
+	}
+
+
+	/* Brightness correction */
+	brightness_factor_r = (brightness_attr->current_value >> 16) & 0xFF;
+	brightness_factor_g = (brightness_attr->current_value >> 8) & 0xFF;
+	brightness_factor_b = brightness_attr->current_value & 0xFF;
+
+	/* The factors are offset by 0x80 because 0x80 is 0 correction */
+	brightness_factor_r -= 0x80;
+	brightness_factor_g -= 0x80;
+	brightness_factor_b -= 0x80;
+
+	for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+		int          new_pixel_val;
+		unsigned int cur_color;
+		unsigned int cur_palette = palette[i];
+
+		/* red: calculate and make sure the result is within range */
+		cur_color     =  (cur_palette >> 16) & 0xFF;
+		new_pixel_val =  cur_color + brightness_factor_r;
+		new_pixel_val =  OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+		palette[i]    &= 0x00FFFF;
+		palette[i]    |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 16;
+
+		/* green: calculate and make sure the result is within range */
+		cur_color     =  (cur_palette >> 8) & 0xFF;
+		new_pixel_val =  cur_color + brightness_factor_g;
+		new_pixel_val =  OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+		palette[i]    &= 0xFF00FF;
+		palette[i]    |= (OS_MAX(new_pixel_val, 0) & 0xFF) << 8;
+
+		/* blue: calculate and make sure the result is within range */
+		cur_color     =  cur_palette & 0xFF;
+		new_pixel_val =  cur_color + brightness_factor_b;
+		new_pixel_val =  OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+		palette[i]    &= 0xFFFF00;
+		palette[i]    |= OS_MAX(new_pixel_val, 0) & 0xFF;
+	}
+
+
+	/* contrast correction */
+	contrast_factor_r = (contrast_attr->current_value >> 16) & 0xFF;
+	contrast_factor_g = (contrast_attr->current_value >> 8) & 0xFF;
+	contrast_factor_b = contrast_attr->current_value & 0xFF;
+
+	/* make sure values are within range */
+	contrast_factor_r -= 0x80;
+	contrast_factor_g -= 0x80;
+	contrast_factor_b -= 0x80;
+
+
+	/* We're doing integer division in this loop using 16i.16f
+	 * integers.  The result will then be converted back into a
+	 * regular, 32-bit integer
+	 */
+	for( i = 0; i < NUM_PALETTE_ENTRIES; i++ ) {
+		int new_pixel_val;
+		unsigned int cur_color;
+		unsigned int cur_palette = palette[i];
+
+		/* red: calculate and make sure the result is within range */
+		if (0 != contrast_factor_r ) {
+			cur_color     = (cur_palette >> 16) & 0xFF;
+			new_pixel_val =
+				(MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_r);
+			new_pixel_val =   new_pixel_val * (cur_color - MID_PIXEL_VAL);
+			new_pixel_val >>= 16;  /* convert back to 32i format */
+			new_pixel_val +=  MID_PIXEL_VAL;
+			new_pixel_val =   OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+			palette[i]    &=  0x00FFFF;  /* clear out the R color */
+			palette[i]    |=  (OS_MAX(new_pixel_val, 0) & 0xFF) << 16;
+		}
+
+		/* green: calculate and make sure the result is within range */
+		if (0 != contrast_factor_g ) {
+			cur_color     = (cur_palette >> 8) & 0xFF;
+			new_pixel_val =
+				(MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_g);
+			new_pixel_val =   new_pixel_val * (cur_color - MID_PIXEL_VAL);
+			new_pixel_val >>= 16;  /* convert back to 32i format */
+			new_pixel_val +=  MID_PIXEL_VAL;
+			new_pixel_val =   OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+			palette[i]    &=  0xFF00FF;  /* clear out the G color */
+			palette[i]    |=  (OS_MAX(new_pixel_val, 0) & 0xFF) << 8;
+		}
+
+		/* blue: calculate and make sure the result is within range */
+		if (0 != contrast_factor_b) {
+			cur_color     = cur_palette & 0xFF;
+			new_pixel_val =
+				(MAX_PIXEL_VAL << 16) / (MAX_PIXEL_VAL - contrast_factor_b);
+			new_pixel_val =   new_pixel_val * (cur_color - MID_PIXEL_VAL);
+			new_pixel_val >>= 16;  /* convert back to 32i format */
+			new_pixel_val +=  MID_PIXEL_VAL;
+			new_pixel_val =   OS_MIN(new_pixel_val, MAX_PIXEL_VAL);
+			palette[i]    &=  0xFFFF00;  /* clear out the B color */
+			palette[i]    |=   OS_MAX(new_pixel_val, 0) & 0xFF;
+		}
+	}
+
+
+	/* write the new values in the palette */
+	for (i = 0; i < NUM_PALETTE_ENTRIES; i++) {
+		/* SDVO palette register is not accesible */
+		EMGD_WRITE32(palette[i],
+			MMIO_TNC(IGD_PORT_LVDS) +
+			pipe->palette_reg + i*4);
+	}
+
+	OS_FREE(palette);
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+
+
+/*!
+ * kms_program_pipe_vga_tnc
+ *
+ * @param emgd_crtc Pointer to our private kms crtc structure
+ *
+ * @return void
+ */
+void kms_program_pipe_vga_tnc(
+	emgd_crtc_t *emgd_crtc)
+{
+	struct drm_device  *dev = NULL;
+	igd_timing_info_t  *timing = NULL;
+	igd_display_pipe_t *pipe = NULL;
+	igd_context_t      *context = NULL;
+	struct drm_encoder *encoder = NULL;
+	emgd_encoder_t     *emgd_encoder = NULL;
+	igd_display_port_t *port = NULL;
+	unsigned long       vga_control;
+	unsigned long       upscale = 0;
+	int                 centering = 1;
+	unsigned long       pt;
+
+	EMGD_TRACE_ENTER;
+
+	pipe = emgd_crtc->igd_pipe;
+	dev = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+	/*
+	 * VGA Plane can attach to only one pipe at a time. LVDS can
+	 * only attach to pipe B. We need to use the display passed to
+	 * determine the pipe number to use. (Napa is same as Alm).
+	 */
+
+	/*
+	 * We can come here with following cases:
+	 *   1. magic->vga    CRT, DVI type displays
+	 *   2. native->vga   int-lvds, and up-scaling lvds displays
+	 *   3. pipe->vga     TV and other unscaled-lvds displays
+	 */
+	vga_control = EMGD_READ32(context->device_context.virt_mmadr + 0x71400);
+	vga_control &= 0x18e3ff00;
+	vga_control |= 0x8e;
+
+	timing = pipe->timing;
+	if(!timing->extn_ptr) {
+		EMGD_ERROR_EXIT("No Extension pointer in program_pipe_vga_tnc");
+		return;
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (((struct drm_crtc *)(&emgd_crtc->base)) == encoder->crtc) {
+			emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+			port = emgd_encoder->igd_port;
+
+		    /* Find UPSCALING attr value*/
+		    pi_pd_find_attr_and_value(port,
+	            PD_ATTR_ID_PANEL_FIT,
+	            0,/*no PD_FLAG for UPSCALING */
+	            NULL, /* dont need the attr ptr*/
+	            &upscale);
+		    /* this PI func will not modify value
+			 * of upscale if attr does not exist
+			 */
+			break;
+		}
+	}
+
+	/* magic->vga || native->vga cases, centering isn't required */
+	if ((timing->width == 720 && timing->height == 400) || upscale) {
+		EMGD_DEBUG("Centering = 0");
+		centering = 0;
+	}
+
+	/* Enable border */
+	if((timing->width >= 800) && !upscale) {
+		EMGD_DEBUG("Enable VGA Border");
+		vga_control |= (1L<<26);
+	}
+
+	if(timing->width == 640) {
+		EMGD_DEBUG("Enable Nine Dot Disable");
+		vga_control |= (1L<<18);
+	}
+
+	if(centering) {
+		EMGD_DEBUG("Enable VGA Center Centering");
+		vga_control |= 1L<<24;
+
+		if(timing->height >= 960) {
+			if(timing->width >= 1280) {
+				EMGD_DEBUG("Enable VGA 2x (Nine Dot Disable)");
+				vga_control |= (1L<<30) | (1L<<18);
+			}
+		}
+	} else {
+		pt = get_port_type(emgd_crtc->crtc_id);
+		if(pt == IGD_PORT_LVDS) {
+			EMGD_DEBUG("Enable VGA Upper-Left Centering & Nine Dot Disable");
+			vga_control |= (1L<<25 | (1L<<18));
+		} else if (upscale) {
+			EMGD_DEBUG("Enable VGA Center Upper-left for upscale ports");
+			vga_control |= 1L<<25;
+		}
+	}
+
+	if(pipe->pipe_num) {
+		vga_control |= 1L<<29;
+	}
+
+	kms_program_pipe_vga(emgd_crtc, (igd_timing_info_t *)timing->extn_ptr);
+	EMGD_WRITE32(vga_control, context->device_context.virt_mmadr + 0x71400);
+
+	EMGD_TRACE_EXIT;
+	return;
+}
+
+
+
+/**
+ * kms_set_pipe_pwr_tnc
+ *
+ * Turns the pipe ON or OFF depending on the input
+ *
+ * @param emgd_crtc (IN) specifies the pipe to change
+ * @param enable    (IN) TRUE to enable pipe, FALSE to disable
+ *
+ * @return
+ */
+static void kms_set_pipe_pwr_tnc(emgd_crtc_t *emgd_crtc, unsigned long enable)
+{
+	unsigned long       pipe_conf;
+	unsigned long       port_type;
+	unsigned long 		temp;
+	struct drm_device  *dev;
+	igd_display_pipe_t *pipe;
+	igd_context_t      *context;
+
+
+	EMGD_TRACE_ENTER;
+
+
+	dev       = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+	context   = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+	pipe      = emgd_crtc->igd_pipe;
+	port_type = get_port_type(emgd_crtc->crtc_id);
+	pipe_conf = READ_MMIO_REG_TNC(port_type, pipe->pipe_reg);
+
+
+	/* Do nothing if current power state is same as what we want to set */
+	/* The PIPE_ENABLE bit is at bit-position 31 */
+	if ( (enable << 31) == (pipe_conf & PIPE_ENABLE) ){
+
+		EMGD_TRACE_EXIT;
+		return;
+	}
+
+
+	if (!enable) {
+
+		/* For SDVO, disable both pipe Bs in 0:2:0 and 0:3:0 */
+		if (IGD_PORT_SDVO == port_type) {
+			WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, pipe->pipe_reg,
+				pipe_conf & ~PIPE_ENABLE);
+		}
+
+		/* Disable pipe */
+		WRITE_MMIO_REG_TNC(port_type, pipe->pipe_reg, pipe_conf & ~PIPE_ENABLE);
+
+		/* check when the pipe is disabled. */
+		wait_pipe(port_type, pipe->pipe_reg, 0);
+
+		/* Make sure the associated DPLL is turned off. */
+		temp = READ_MMIO_REG_TNC(port_type, pipe->clock_reg->dpll_control);
+		if (temp & BIT31) {
+			/* Double buffered */
+			WRITE_MMIO_REG_TNC(port_type, pipe->clock_reg->dpll_control,
+				temp & ~BIT31);
+			WRITE_MMIO_REG_TNC(port_type, pipe->clock_reg->dpll_control,
+				temp & ~BIT31);
+		}
+
+
+		EMGD_DEBUG("Set Pipe Power: OFF");
+
+	} else {
+
+		if (IGD_PORT_SDVO == port_type) {
+			WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, pipe->pipe_reg,
+				pipe_conf | PIPE_ENABLE);
+		}
+
+		/* Enable pipe */
+		WRITE_MMIO_REG_TNC(port_type, pipe->pipe_reg, pipe_conf | PIPE_ENABLE);
+
+		EMGD_DEBUG("Set Pipe Power: ON");
+	}
+
+
+	EMGD_TRACE_EXIT;
+	return;
+}
+
+
+
+/**
+ * kms_program_pipe_tnc
+ *
+ * Called before a mode set, takes the input "mode", matches it to the closest
+ * supported mode, then put the supported mode into "adjusted_mode" to let the
+ * caller know.
+ *
+ * @param encoder (IN) Encoder being prepared
+ *
+ * @return true, false (details TBD)
+ */
+static void kms_program_pipe_tnc(emgd_crtc_t *emgd_crtc)
+{
+	unsigned long       timing_reg;
+	unsigned long       pipe_conf;
+	unsigned long       hactive, vactive;
+	short               hactive_tmp, vactive_tmp;
+	igd_timing_info_t  *current_timings;
+	igd_timing_info_t   pTimings_tmp;
+	struct drm_device  *dev          = NULL;
+	igd_display_pipe_t *pipe         = NULL;
+	igd_display_port_t *port         = NULL;
+	igd_context_t      *context      = NULL;
+	struct drm_encoder *encoder      = NULL;
+	emgd_encoder_t     *emgd_encoder = NULL;
+	pd_timing_t        *vga_timing   = NULL;
+
+	unsigned long flag_clip_fix;
+	unsigned long pipe_reg;
+	unsigned long temp;
+	unsigned long pt;
+	unsigned long dc;
+	unsigned long calc;
+	int           i;
+	tnc_wa_timing_t *wa;
+	/* igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info; */
+	platform_context_tnc_t *platform_context;
+
+	EMGD_TRACE_ENTER;
+
+	pipe            = emgd_crtc->igd_pipe;
+	current_timings = pipe->timing;
+	vga_timing      = (pd_timing_t *) current_timings->extn_ptr;
+	pipe_reg        = pipe->pipe_reg;
+
+	pt       = get_port_type(emgd_crtc->crtc_id);
+	dev      = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+	context  = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+	platform_context = (platform_context_tnc_t *) mode_context->context->platform_context;
+	flag_clip_fix    = mode_context->clip_hw_fix;
+
+	EMGD_DEBUG("Device power state: D%ld", context->device_context.power_state);
+
+	pipe_conf = READ_MMIO_REG_TNC(pt, pipe->pipe_reg);
+
+	/* Preserving bits 0:17, bit 20, bit 24, bit 26, bit 29:30.  The spec on
+	 * which bits to preserve has been updated since we've originally written
+	 * the code for the non-KMS path.  However, to minimize risk of this fix,
+	 * we are only updating them here.  This is why we are not using
+	 * device_data_tnc->pipe_preserve.  */
+	pipe_conf &= 0x6513FFFF;
+
+	/* For TNC B1, enable hardware cliping fix*/
+	if((platform_context->tnc_dev3_rid == TNC_B1_DEV3_RID)&&
+		(flag_clip_fix & IGD_CLIP_FIX_GLOBAL_ENABLE)) {
+
+		/* Disable SDVO Pipe in Device 2 and Device 3 */
+		WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, pipe->pipe_reg,
+			pipe_conf & (~0x80000000L));
+
+		WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, pipe->pipe_reg,
+			pipe_conf & (~0x80000000L));
+
+		/* check when the pipe is disabled. */
+		wait_pipe(IGD_PORT_LVDS, pipe->pipe_reg, 0);
+
+		/* Enable clipping hardware fix */
+		temp = READ_MMIO_REG_TNC(IGD_PORT_LVDS, DSP_CHICKENBITS);
+		if(flag_clip_fix & IGD_CLIP_FIX_REPLACE_STALL) {
+			temp |= BIT18;
+		} else {
+			temp &= ~BIT18;
+		}
+		if(flag_clip_fix & IGD_CLIP_FIX_DISABLE_THROTTLE) {
+			temp |= BIT15;
+		} else {
+			temp &= ~BIT15;
+		}
+		WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, DSP_CHICKENBITS, temp);
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (((struct drm_crtc *)(&emgd_crtc->base)) == encoder->crtc) {
+			emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+			port = emgd_encoder->igd_port;
+			break;
+		}
+	}
+
+	if (NULL == emgd_encoder) {
+		EMGD_ERROR_EXIT("Invalid CRTC selected.");
+		return;
+	}
+
+	/* Debug messages */
+	EMGD_DEBUG("Current timings %ux%u mode_number = %u "
+			   "mode_info_flags = 0x%lx, dclk = %lu",
+			   current_timings->width,
+			   current_timings->height,
+			   current_timings->mode_number,
+			   current_timings->mode_info_flags,
+			   current_timings->dclk);
+
+	if (vga_timing) {
+	  EMGD_DEBUG("ext_timing %ux%u mode_number = %u "
+				 "mode_info_flags= 0x%lx, dclk = %lu",
+				 vga_timing->width,
+				 vga_timing->height,
+				 vga_timing->mode_number,
+				 vga_timing->mode_info_flags,
+				 vga_timing->dclk);
+	}
+
+
+	/*
+	 * If the mode is VGA and the PD says it handles all VGA modes without
+	 * reprogramming then just set the mode and leave centering off.
+	 */
+	if(current_timings->mode_info_flags & IGD_MODE_VESA) {
+		EMGD_DEBUG("IGD_MODE_VESA");
+
+		if (current_timings->mode_number <= VGA_MODE_NUM_MAX) {
+			EMGD_DEBUG("current_timings->mode_number <= VGA_MODE_NUM_MAX");
+			kms_program_pipe_vga_tnc(emgd_crtc);
+
+			EMGD_TRACE_EXIT;
+			return;
+		}
+	}
+
+	/* Program dot clock divisors. */
+	kms_program_clock_tnc(emgd_crtc, pipe->clock_reg, current_timings->dclk);
+
+	/* Program timing registers for the pipe */
+	timing_reg = pipe->timing_reg;
+	if (current_timings->mode_info_flags & IGD_PIXEL_DOUBLE) {
+		hactive = (unsigned long)current_timings->width*2 - 1;
+	} else {
+		hactive = (unsigned long)current_timings->width - 1;
+	}
+
+	if (current_timings->mode_info_flags & IGD_LINE_DOUBLE) {
+		vactive = (unsigned long)current_timings->height*2 - 1;
+	} else {
+		/* For Atom E6xx Hardware will automatically divide by 2 to
+		   get the number of line in each field */
+		vactive = (unsigned long)current_timings->height - 1;
+	}
+
+
+	/* Reset the Palette */
+	for (i = 0; i < 256; i++) {
+		/* Program each of the 256 4-byte palette entries */
+		WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, pipe->palette_reg + (i << 2),
+			((i<<16) | (i<<8) | i));
+	}
+
+	if (port) {
+		/* apply color correction */
+		for( i = 0; PD_ATTR_LIST_END != port->attributes[i].id; i++ ) {
+
+			if ((PD_ATTR_ID_FB_GAMMA      == (port->attributes[i].id)) ||
+				(PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)) ||
+				(PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)))  {
+
+				set_color_correct_tnc(emgd_crtc);
+			}
+		}
+	}
+
+
+	/*
+	 * NOTE: For size reasons the timng table contains unsigned short
+	 * values. Don't shift them past 16. Use a temp instead.
+	 * All register offsets and bit shift are verified for Gen4
+	 *
+	 * For SDVO display:
+	 * Write values into pipe B registers in both 0:2:0 and 0:3:0
+	 */
+
+	dc = *(context->mod_dispatch.dsp_current_dc);
+
+	wa = WA_TUNE;
+
+	for (i=0; i<2; i++) {
+		/* Temp variable */
+		pTimings_tmp = *current_timings;
+		hactive_tmp  = (short) hactive;
+		vactive_tmp  = (short) vactive;
+
+		/* This work around is only for Atom E6xx B0 */
+		if((IGD_DC_CLONE(dc) || IGD_DC_EXTENDED(dc))
+			&& pt == IGD_PORT_SDVO &&
+			(context->device_context.rid == TNC_B0_RID)
+			&& FLAG(flag_basic_htotal_formula_wa)){
+
+			if(!(current_timings->reserved_dd & TNC_HTOTAL_TUNED)){
+				/* Modify blanks so it always begin after active pixel and ends
+				 * at the end. Do not change it if we are already tuned to
+				 * maintain original timing specification
+				 */
+				pTimings_tmp.hblank_start =
+								(short) (current_timings->width - 1);
+				pTimings_tmp.vblank_start =
+								(short) (current_timings->height - 1);
+				pTimings_tmp.hblank_end = (short) (current_timings->htotal);
+				pTimings_tmp.vblank_end = (short) (current_timings->vtotal);
+			}
+
+			if(i==0){
+				if(current_timings->reserved_dd == 0 ||
+					(wa->counter > LIMIT_TOTAL_CHECK_DISPLAY)){
+					/* First time tuning */
+					if ((mode_context->ref_freq != 0) &&
+							(mode_context->ref_freq >= 190000) &&
+							(mode_context->ref_freq <= 210000)){
+						calc = (current_timings->htotal *
+									mode_context->ref_freq);
+					} else {
+						calc = (current_timings->htotal * LNC_CLOCK);
+					}
+
+					calc = (calc / (pipe->clock_reg->actual_dclk));
+					calc *= (current_timings->vtotal -1);
+					calc /= current_timings->vtotal;
+					pTimings_tmp.htotal = (short)calc;
+					current_timings->reserved_dd = wa->htotal =
+						pTimings_tmp.htotal;
+					EMGD_DEBUG("Delta = %d", wa->htotal);
+				}else if (current_timings->reserved_dd & TNC_HTOTAL_TUNED){
+					pTimings_tmp.htotal =
+						(short)(current_timings->reserved_dd &
+								(~TNC_HTOTAL_TUNED));
+				}else{
+					if(wa->htotal == 0)
+						wa->htotal = (short)current_timings->reserved_dd;
+					pTimings_tmp.htotal = wa->htotal;
+				}
+				/* Use vphase formula if available */
+				if(vphase){
+					pTimings_tmp.vtotal -= (short)vphase;
+					pTimings_tmp.vsync_start -= (short)vphase;
+					pTimings_tmp.vsync_end -= (short)vphase;
+					pTimings_tmp.vblank_end -= (short)vphase;
+				}else{
+					pTimings_tmp.hblank_end +=
+						(short) (pTimings_tmp.htotal - current_timings->htotal);
+				}
+			}
+		}
+
+
+		/* Program Timings */
+		temp = (unsigned long)(pTimings_tmp.htotal) << 16 | hactive_tmp;
+		WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg, temp);
+
+		temp = ((unsigned long) pTimings_tmp.hblank_end << 16) |
+			(unsigned long)(pTimings_tmp.hblank_start);
+		WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x04, temp);
+
+		temp = ((unsigned long)(current_timings->hsync_end) << 16) |
+			(unsigned long)(current_timings->hsync_start);
+		WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x08, temp);
+
+		temp = ((unsigned long)(pTimings_tmp.vtotal) << 16) | vactive_tmp;
+		WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x0C, temp);
+
+		temp = ((unsigned long)(pTimings_tmp.vblank_end) << 16) |
+			(unsigned long)(pTimings_tmp.vblank_start);
+		WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x10, temp);
+
+		temp = ((unsigned long)(pTimings_tmp.vsync_end)<< 16) |
+			(unsigned long)(pTimings_tmp.vsync_start);
+		WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x14, temp);
+
+		/*
+		 * If there is a linked mode it is either the VGA or a scaled
+		 * mode. If it is scaled then we need to use it as the source size.
+		 */
+		if (current_timings->extn_ptr) {
+			igd_timing_info_t *scaled_timings =
+				(igd_timing_info_t *)current_timings->extn_ptr;
+
+			if((scaled_timings->mode_info_flags & IGD_MODE_VESA) &&
+				(scaled_timings->mode_number <= VGA_MODE_NUM_MAX)) {
+				temp = (hactive << 16) | vactive;
+			} else {
+				EMGD_DEBUG("scaled_timings->width [%d], "
+						   "scaled_timings->height [%d]\n",
+					scaled_timings->width, scaled_timings->height);
+				temp = (unsigned long)scaled_timings->width  - 1;
+				temp = (temp << 16) |
+					(unsigned long)(scaled_timings->height - 1);
+			}
+		} else {
+			temp = (hactive_tmp << 16) | vactive_tmp;
+		}
+		WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x1C, temp);
+
+		/* Put pipe in interlaced mode if requested:
+		 *     should only happen for LVDS display if at all. */
+		if (current_timings->mode_info_flags & IGD_SCAN_INTERLACE) {
+			pipe_conf |= (INTERLACE_EN);
+		} else {
+			pipe_conf &= ~(INTERLACE_EN);
+		}
+
+		pipe_conf |= PIPE_ENABLE;
+		WRITE_MMIO_REG_TNC(ports_tnc[i], pipe->pipe_reg, pipe_conf);
+		WRITE_MMIO_REG_TNC(ports_tnc[i], pipe->pipe_reg, pipe_conf);
+
+		/* For LVDS port, don't touch dev3 registers stop after 1st iteration */
+		if (pt == IGD_PORT_LVDS) {
+			break;
+		}
+	}
+
+
+	/* Gen4 can check when the pipe is enabled. */
+	wait_pipe(IGD_PORT_LVDS, pipe->pipe_reg, 0x40000000);
+
+	/*
+	 * Set the VGA address range to 0xa0000 so that a normal (not VGA)
+	 * mode can be accessed through 0xa0000 in a 16bit world.
+	 */
+	WRITE_AR(context->device_context.virt_mmadr, 0x10, 0xb);
+	WRITE_VGA(context->device_context.virt_mmadr, GR_PORT, 0x06, 0x5);
+	WRITE_VGA(context->device_context.virt_mmadr, GR_PORT, 0x10, 0x1);
+
+	if(current_timings->extn_ptr) {
+		/* This means either internal scaling (LVDS) or centered VGA */
+		current_timings = current_timings->extn_ptr;
+		if(current_timings->extn_ptr) {
+			/* This is both the scaled and centered VGA */
+			current_timings = current_timings->extn_ptr;
+		}
+		if (current_timings->mode_info_flags & IGD_MODE_VESA) {
+			if (current_timings->mode_number <= VGA_MODE_NUM_MAX) {
+				kms_program_pipe_vga_tnc(emgd_crtc);
+			}
+		}
+	}
+
+	if (pt == IGD_PORT_SDVO) {
+		/*  Enable Chicken Bit */
+		/*  Setting BIT6 enable Pipe B Palette Write
+         *  to prevent hang during palette write */
+		temp = READ_MMIO_REG_TNC(IGD_PORT_LVDS, DSP_CHICKENBITS);
+		WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, DSP_CHICKENBITS, temp | BIT6);
+	}
+
+	EMGD_TRACE_EXIT;
+	return;
+}
+
+
+
+static void kms_set_plane_pwr_tnc(emgd_crtc_t *emgd_crtc, unsigned long enable)
+{
+	unsigned long           plane_control;
+	unsigned long           plane_reg;
+	struct drm_device      *dev         = NULL;
+	igd_display_plane_t    *plane       = NULL;
+	igd_display_pipe_t     *pipe        = NULL;
+	igd_context_t          *context     = NULL;
+
+	EMGD_TRACE_ENTER;
+
+	EMGD_DEBUG("Program Plane: %s", enable?"ENABLE":"DISABLE");
+
+	pipe    = emgd_crtc->igd_pipe;
+	dev     = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+	plane   = PLANE(pipe->owner);
+
+	if (!plane) {
+		EMGD_ERROR_EXIT("Trying to set power to a plane that is not tied "
+			" to a crtc.");
+		return;
+	}
+
+	/* In case a plane update is already in progress */
+	wait_for_vblank_tnc(pipe->pipe_reg);
+
+	/* Get the current value of the plane control register */
+	plane_reg     = plane->plane_reg;
+	plane_control = EMGD_READ32(context->device_context.virt_mmadr + plane_reg);
+
+	if((enable == FALSE) ||
+		(context->device_context.power_state != IGD_POWERSTATE_D0)) {
+		/*
+		 * Note: The vga programming code does not have an "off". So
+		 * when programming the plane to off we make sure VGA is off
+		 * as well.
+		 */
+		disable_vga_tnc(context->device_context.virt_mmadr);
+
+		/* The Sprite and Cursor planes need to turned off for the modeset
+		   to succeed. */
+       	EMGD_WRITE32(0x0, context->device_context.virt_mmadr + DSPCCNTR);
+       	EMGD_WRITE32(0x0, context->device_context.virt_mmadr + DSPCCNTR + DSP_START_OFFSET);
+
+       	EMGD_WRITE32(0x0, context->device_context.virt_mmadr + CUR_B_CNTR);
+       	EMGD_WRITE32(0x0, context->device_context.virt_mmadr + CUR_B_CNTR + CUR_BASE_OFFSET);
+
+       	EMGD_WRITE32(0x0, context->device_context.virt_mmadr + CUR_A_CNTR);
+       	EMGD_WRITE32(0x0, context->device_context.virt_mmadr + CUR_B_CNTR + CUR_BASE_OFFSET);
+
+		/*
+		 * To turn off plane A or B, the program have to trigger the plane A
+		 * or B start register.  Or else, it will not work.
+		 */
+		plane_control &= ~BIT31;
+
+		EMGD_WRITE32(plane_control,
+						context->device_context.virt_mmadr + plane_reg);
+
+		EMGD_WRITE32(EMGD_READ32(context->device_context.virt_mmadr +
+			plane_reg + DSP_START_OFFSET),
+			context->device_context.virt_mmadr + plane_reg + DSP_START_OFFSET);
+	} else {
+		/* Enable Plane */
+		plane_control |= BIT31;
+
+		EMGD_WRITE32(plane_control,
+			context->device_context.virt_mmadr + plane_reg);
+
+		EMGD_WRITE32(EMGD_READ32(context->device_context.virt_mmadr +
+			plane_reg + DSP_START_OFFSET),
+			context->device_context.virt_mmadr + plane_reg + DSP_START_OFFSET);
+	}
+
+
+	wait_for_vblank_tnc(pipe->pipe_reg);
+	EMGD_TRACE_EXIT;
+	return;
+}
+
+
+
+static void kms_program_plane_tnc(emgd_crtc_t *emgd_crtc, unsigned long status)
+{
+	unsigned long stride;
+	unsigned long stereo;
+	unsigned long plane_control;
+	unsigned long other_plane_reg;
+	igd_timing_info_t      *timing      = NULL;
+	igd_framebuffer_info_t *fb_info     = NULL;
+	unsigned long           plane_reg;
+	struct drm_device      *dev         = NULL;
+	igd_display_plane_t    *plane       = NULL;
+	igd_display_pipe_t     *pipe        = NULL;
+	igd_context_t          *context     = NULL;
+	igd_timing_info_t      *pipe_timing = NULL;
+	unsigned long           ulreg       = 0;
+	unsigned long           b_reg       = 0;
+	/* tnc_wa_timing_t *wa = WA_TUNE; */
+
+	EMGD_TRACE_ENTER;
+
+
+	pipe    = emgd_crtc->igd_pipe;
+	dev     = ((struct drm_crtc *)(&emgd_crtc->base))->dev;
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+	plane     = PLANE(pipe->owner);
+	if (!plane) {
+		EMGD_ERROR("Trying to program a plane that is not tied to a crtc.");
+		return;
+	}
+	fb_info   = plane->fb_info;
+	plane_reg = plane->plane_reg;
+
+
+	EMGD_DEBUG("Device power state: D%ld", context->device_context.power_state);
+
+	wait_for_vblank_tnc(pipe->pipe_reg);
+
+	plane_control = EMGD_READ32(context->device_context.virt_mmadr + plane_reg);
+	if(plane->plane_reg == DSPACNTR) {
+		plane_control &= device_data_tnc->plane_a_preserve;
+	} else { /* if it's plane b or plane c */
+		plane_control &= device_data_tnc->plane_b_c_preserve;
+	}
+
+
+	/*
+	 * Note: The very first pass through this function will be with
+	 * status false and timings == NULL. Don't use the timings before
+	 * the check above.
+	 */
+	timing = pipe->timing;
+	pipe_timing = timing;
+	/* There is a special case code for legacy VGA modes */
+	while (timing->extn_ptr) {
+		timing = (igd_timing_info_t *)timing->extn_ptr;
+	}
+	if(MODE_IS_VGA(timing) && CHECK_VGA(pipe_timing)) {
+		kms_program_plane_vga(context->device_context.virt_mmadr, timing);
+		EMGD_TRACE_EXIT;
+		return;
+	}
+
+	disable_vga_tnc(context->device_context.virt_mmadr);
+
+	/* enable plane, select pipe, enable gamma correction logic */
+	plane_control |= (pipe->pipe_num<<24);
+	pipe->plane = plane;
+	plane_control |= (1<<30);
+
+
+	/* Here the settings:
+	 *   If line + pixel dbling, set 21,20 to 01b, and set Horz Multiply
+	 *   If line dbling only,    set 21,20 to 11b
+	 *   If pixel dbling only,   set 21,20 to 00b, but set Horz Multiply
+	 *   If no doubling,         set 21,20 to 00b (no Horz Multiply)
+	 * For pixel doubling
+	 *           --> both progressive/interlaced modes
+	 * For Line doubling
+	 *           --> progressive modes only
+	 */
+
+	if (!(timing->mode_info_flags & IGD_SCAN_INTERLACE)) {
+		/* Line doubling in progressive mode requires special bits */
+		if (timing->mode_info_flags & IGD_LINE_DOUBLE) {
+			/* BIT 20 for line & pixel doubling*/
+			plane_control |= BIT20;
+			/* check later, if no pixel doubling, set bit 21 too*/
+		}
+	}
+	if (timing->mode_info_flags & IGD_PIXEL_DOUBLE) {
+		/* For line ONLY doubling, set bit 21 also '1' */
+		plane_control |= BIT21;
+	}
+
+	kms_mode_get_stride_stereo_tnc(pipe, plane, &stride, &stereo, 0);
+
+	/* set color depth */
+	switch (IGD_PF_DEPTH(fb_info->pixel_format)) {
+	case PF_DEPTH_8:
+		plane_control |= BIT27 | BIT30;
+		break;
+	case PF_DEPTH_16:
+		plane_control |= BIT28 | BIT26;
+		break;
+	default:
+	case PF_DEPTH_32:
+		plane_control |= BIT28 | BIT27;
+		break;
+	}
+
+	if(fb_info->flags & IGD_ENABLE_DISPLAY_GAMMA) {
+		plane_control |= (BIT30);
+	}
+
+	if(fb_info->flags & IGD_SURFACE_TILED) {
+		plane_control |= (BIT10);
+	}
+
+	/* Set watermark for Atom E6xx */
+	if (!mode_context->en_reg_override) {
+		if (plane_reg == DSPACNTR) {
+			other_plane_reg = DSPBCNTR;
+		} else {
+			other_plane_reg = DSPACNTR;
+		}
+
+		if (EMGD_READ32(context->device_context.virt_mmadr + other_plane_reg) &
+				0x80000000) {
+
+			EMGD_WRITE32(device_data_tnc->dsp_arb,
+				context->device_context.virt_mmadr + PIPEA_DISP_ARB_CTRL);
+		} else if (plane_reg == DSPACNTR) {
+			EMGD_WRITE32(0x00003fff,
+				context->device_context.virt_mmadr + PIPEA_DISP_ARB_CTRL);
+		} else {
+			EMGD_WRITE32(0x00003f80,
+				context->device_context.virt_mmadr + PIPEA_DISP_ARB_CTRL);
+		}
+
+		/*
+		 * Setting WM priority level to 11
+		 * to workaround display bouncing issues
+		 * TODO: Mode set from Clone->Single(Primary)
+		 * PIPEA_DISP_ARB_CTRL does not get updated
+		 */
+		ulreg = EMGD_READ32(context->device_context.virt_mmadr + 0x00020f8);
+		EMGD_WRITE32(ulreg | 0x000003f0,
+		context->device_context.virt_mmadr + 0x00020f8);
+
+		EMGD_WRITE32(device_data_tnc->fifo_watermark1,
+			context->device_context.virt_mmadr + FW_1);
+		EMGD_WRITE32(device_data_tnc->fifo_watermark2,
+			context->device_context.virt_mmadr + FW_2);
+		EMGD_WRITE32(device_data_tnc->fifo_watermark3,
+			context->device_context.virt_mmadr + FW_3);
+		EMGD_WRITE32(device_data_tnc->fifo_watermark4,
+			context->device_context.virt_mmadr + FW_4);
+		EMGD_WRITE32(device_data_tnc->fifo_watermark5,
+			context->device_context.virt_mmadr + FW_5);
+		EMGD_WRITE32(device_data_tnc->fifo_watermark6,
+			context->device_context.virt_mmadr + FW_6);
+	} else {
+		/* en_reg_override=1 */
+		/* Override display registers */
+		EMGD_WRITE32(mode_context->gvd_hp_control,
+			context->device_context.virt_mmadr + 0x00020f8);
+		EMGD_WRITE32(mode_context->disp_arb,
+			context->device_context.virt_mmadr + PIPEA_DISP_ARB_CTRL);
+		EMGD_WRITE32(mode_context->fifo_watermark1,
+			context->device_context.virt_mmadr + FW_1);
+		EMGD_WRITE32(mode_context->fifo_watermark2,
+			context->device_context.virt_mmadr + FW_2);
+		EMGD_WRITE32(mode_context->fifo_watermark3,
+			context->device_context.virt_mmadr + FW_3);
+		EMGD_WRITE32(mode_context->fifo_watermark4,
+			context->device_context.virt_mmadr + FW_4);
+		EMGD_WRITE32(mode_context->fifo_watermark5,
+			context->device_context.virt_mmadr + FW_5);
+		EMGD_WRITE32(mode_context->fifo_watermark6,
+			context->device_context.virt_mmadr + FW_6);
+		EMGD_WRITE32(mode_context->disp_chicken_bits,
+			context->device_context.virt_mmadr + 0x0070400);
+
+		/* Override Bunit Chickenbits and BWFLUSH register */
+		write_bunit_tnc(0x30, mode_context->bunit_chicken_bits);
+		write_bunit_tnc(0x02, mode_context->bunit_write_flush);
+	}
+
+	EMGD_DEBUG(" GVD HP_CONTROL: 0x%lx", ulreg);
+	ulreg = EMGD_READ32(context->device_context.virt_mmadr +
+				PIPEA_DISP_ARB_CTRL);
+	EMGD_DEBUG(" Display Arbitration register: 0x%lx", ulreg);
+	ulreg = EMGD_READ32(context->device_context.virt_mmadr + FW_1);
+	EMGD_DEBUG(" FIFO Watermark Control Register 1: 0x%lx", ulreg);
+	ulreg = EMGD_READ32(context->device_context.virt_mmadr + FW_2);
+	EMGD_DEBUG(" FIFO Watermark Control Register 2: 0x%lx", ulreg);
+	ulreg = EMGD_READ32(context->device_context.virt_mmadr + FW_3);
+	EMGD_DEBUG(" FIFO Watermark Control Register 3: 0x%lx", ulreg);
+	ulreg = EMGD_READ32(context->device_context.virt_mmadr + FW_4);
+	EMGD_DEBUG(" FIFO Watermark Control Register 4: 0x%lx", ulreg);
+	ulreg = EMGD_READ32(context->device_context.virt_mmadr + FW_5);
+	EMGD_DEBUG(" FIFO Watermark Control Register 5: 0x%lx", ulreg);
+	ulreg = EMGD_READ32(context->device_context.virt_mmadr + FW_6);
+	EMGD_DEBUG(" FIFO Watermark Control Register 6: 0x%lx", ulreg);
+	ulreg = EMGD_READ32(context->device_context.virt_mmadr + DSP_CHICKENBITS);
+	EMGD_DEBUG(" Display Chicken bits: 0x%lx", ulreg);
+	read_bunit_tnc(0x30, &b_reg);
+	EMGD_DEBUG(" Bunit Chicken bits: 0x%lx", b_reg);
+	read_bunit_tnc(0x02, &b_reg);
+	EMGD_DEBUG(" Bunit Write Flush: 0x%lx", b_reg);
+
+
+	/* FIXME: Not required for TNC.
+	 * The B-Spec states that rendering will be slower if the fences are not
+	 * a power of 2.  So for now, always use a power of 2. */
+	/* EMGD_WRITE32(0x04000400, context->device_context.virt_mmadr + 0x209c); */
+
+	EMGD_DEBUG(" Plane Control:  0x%lx", plane_control);
+	EMGD_DEBUG(" Plane Base:     0x%lx", fb_info->fb_base_offset);
+	EMGD_DEBUG(" Visible Offset: 0x%lx", fb_info->visible_offset);
+	EMGD_DEBUG(" Plane Pitch:    0x%lx", stride);
+
+	EMGD_WRITE32(plane_control, context->device_context.virt_mmadr + plane_reg);
+	EMGD_WRITE32(stride,
+		context->device_context.virt_mmadr + plane_reg + DSP_STRIDE_OFFSET);
+
+	EMGD_WRITE32(fb_info->visible_offset,
+		context->device_context.virt_mmadr + plane_reg + DSP_LINEAR_OFFSET);
+	EMGD_WRITE32(0, context->device_context.virt_mmadr + plane_reg + 0x24);
+	EMGD_WRITE32(fb_info->fb_base_offset,
+		context->device_context.virt_mmadr + plane_reg + DSP_START_OFFSET);
+
+	wait_for_vblank_tnc(pipe->pipe_reg);
+
+	EMGD_TRACE_EXIT;
+}
+
+
+/*!
+ *
+ * @param emgd_encoder
+ * @param status
+ *
+ * @return program_port_lvds_gen4()
+ * @return program_port_sdvo_gen4()
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int kms_program_port_tnc(emgd_encoder_t *emgd_encoder,
+		unsigned long status)
+{
+	EMGD_TRACE_ENTER;
+
+	if (emgd_encoder->igd_port->port_type == IGD_PORT_LVDS) {
+		EMGD_TRACE_EXIT;
+		return kms_program_port_lvds_tnc(emgd_encoder, status);
+	} else {
+		EMGD_TRACE_EXIT;
+		return kms_program_port_sdvo_tnc(emgd_encoder, status);
+	}
+}
+
+
+/*!
+ *
+ * @param emgd_encoder
+ * @param status
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+int kms_program_port_lvds_tnc(emgd_encoder_t *emgd_encoder,
+		unsigned long status)
+{
+	int ret = 0;
+	unsigned long pd_powerstate = PD_POWER_MODE_D3;
+	pd_timing_t        *timing    = NULL;
+	igd_display_port_t *port      = NULL;
+	struct drm_encoder *encoder   = NULL;
+	struct drm_device  *dev       = NULL;
+	igd_context_t      *context   = NULL;
+	struct drm_crtc    *crtc      = NULL;
+	emgd_crtc_t        *emgd_crtc = NULL;
+	igd_display_pipe_t *pipe      = NULL;
+
+	EMGD_TRACE_ENTER;
+
+	encoder = &emgd_encoder->base;
+	port = emgd_encoder->igd_port;
+	dev = encoder->dev;
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+	EMGD_DEBUG("Program LVDS: (%s)", status?"ENABLE":"DISABLE");
+
+	if (status == TRUE) {
+
+		if(!(port->pt_info->flags & IGD_DISPLAY_ENABLE)) {
+			EMGD_TRACE_EXIT;
+			return 0;
+		}
+
+		pd_powerstate = (context->device_context.power_state > port->power_state) ?
+			context->device_context.power_state : port->power_state;
+
+		if (pd_powerstate == IGD_POWERSTATE_D0) {
+			EMGD_DEBUG("Power State: D0");
+
+			list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+				if (crtc == encoder->crtc) {
+					emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+					pipe = emgd_crtc->igd_pipe;
+					break;
+				}
+			}
+
+			timing = (pd_timing_t *)pipe->timing;
+			/* Reach end timing to get user resolution and pass it to pd */
+			if(timing->extn_ptr) {
+				timing = (pd_timing_t *)timing->extn_ptr;
+			}
+			/* set mode will take care of port control */
+			ret = port->pd_driver->set_mode(
+					port->pd_context,
+					timing,
+					1<<pipe->pipe_num);
+		}
+	}
+
+	/* either status == FALSE, or status == TRUE, but powerstate is D1/D2/D3 */
+	if (pd_powerstate != IGD_POWERSTATE_D0) {
+		ret = port->pd_driver->set_power(
+			port->pd_context, PD_POWER_MODE_D3);
+	}
+
+	if (ret) {
+		EMGD_ERROR_EXIT("PD set_%s returned: 0x%x",
+			(pd_powerstate == IGD_POWERSTATE_D0)?"mode":"power", ret);
+		return -IGD_ERROR_INVAL;
+	}
+
+	EMGD_TRACE_EXIT;
+	return ret;
+}
+
+
+/*!
+ *
+ * @param emgd_encoder
+ * @param status
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_INVAL on failure
+ */
+static int kms_program_port_sdvo_tnc(emgd_encoder_t *emgd_encoder,
+		unsigned long status)
+{
+	unsigned long port_control;
+	unsigned long pd_powerstate = PD_POWER_MODE_D3;
+	unsigned long upscale = 0;
+	igd_timing_info_t  local_timing;
+	igd_timing_info_t  *timing    = NULL;
+	igd_display_port_t *port      = NULL;
+	struct drm_encoder *encoder   = NULL;
+	struct drm_device  *dev       = NULL;
+	igd_context_t      *context   = NULL;
+	struct drm_crtc    *crtc      = NULL;
+	emgd_crtc_t        *emgd_crtc = NULL;
+	igd_display_pipe_t *pipe      = NULL;
+	unsigned long temp;
+	int ret;
+
+	EMGD_TRACE_ENTER;
+
+	encoder = &emgd_encoder->base;
+	port = emgd_encoder->igd_port;
+	dev = encoder->dev;
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+	EMGD_DEBUG("Program Port: (%s)", status?"ENABLE":"DISABLE");
+	EMGD_DEBUG("pd_flags: 0x%lx", port->pd_flags);
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (crtc == encoder->crtc) {
+			emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+			pipe = emgd_crtc->igd_pipe;
+			break;
+		}
+	}
+
+	timing = pipe->timing;
+
+	port_control = READ_MMIO_REG_TNC(IGD_PORT_SDVO, port->port_reg);
+
+	if (status == TRUE) {
+		if (!(port->pt_info->flags & IGD_DISPLAY_ENABLE)) {
+			EMGD_TRACE_EXIT;
+			return 0;
+		}
+
+		/* Enable VGA syncs for native vga modes */
+		if (port->vga_sync == 1) {
+			EMGD_DEBUG("VGA sync true, is width x height 720 x 400?");
+			if((timing->width == 720) && (timing->height == 400)) {
+				EMGD_DEBUG("Modify port control and multi_port_control");
+				port_control |= (1L<<15);
+			}
+		}
+
+		/* Fact that both IGD_ powerstates and PD_ powermodes have
+		 * same definitions */
+		pd_powerstate =
+			(context->device_context.power_state > port->power_state) ?
+			context->device_context.power_state : port->power_state;
+
+		if (pd_powerstate == IGD_POWERSTATE_D0) {
+			EMGD_DEBUG("Power State: D0");
+			/* Upscale */
+			pi_pd_find_attr_and_value(port,
+				PD_ATTR_ID_PANEL_FIT,
+				0, /*no PD_FLAG for UPSCALING */
+				NULL, /* dont need the attr ptr*/
+				&upscale);
+
+			/* Reach the end timing if upscaling is enabled */
+			if (timing->extn_ptr && upscale) {
+				timing = (pd_timing_t *)timing->extn_ptr;
+			}
+
+			local_timing = *timing;
+			if (upscale) {
+				/* For timings smaller than width 360 and height 200,
+				 * double the size. This is because the active area of the mode
+				 * is double the size of the resolution for these modes
+				 *  - Very tricky huh */
+				if (local_timing.width <= 360) {
+					local_timing.width <<= 1;
+				}
+				if (local_timing.height <= 200) {
+					local_timing.height <<= 1;
+				}
+			}
+
+			/* BIT31 - Enable
+			 * BIT30 - PIPE B
+			 * BIT29 - Stall
+			 * BIT7  - Border
+			 */
+			port_control |= BIT31|BIT30|BIT29|BIT7;
+
+			/* Program cDVO registers:
+			 * Keep default values for
+			 *     7000h - cDVO control register
+			 *     7004h - cDVO slew rate register
+			 *     7008h - cDVO strength register
+			 *     700Ch - cDVO RCOMP update register
+			 *     6102Ch - cDVO stall register = 0xA.
+			 * Note: Though EAS says 6102Ch default value is 6, it is a typo
+			 *     in the spec, based on Si DE hw default value is 10 (0xA),
+			 *     so no need to program explicitly. This saves few bytes for
+			 *     micro.
+			 */
+
+			/* Enable Current Source */
+			temp = READ_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG);
+			temp |= 0x2000;
+			WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, SDVO_BUFF_CTRL_REG, temp);
+		}
+	}
+
+	if (pd_powerstate == PD_POWER_MODE_D0) {
+		ret = port->pd_driver->set_mode(port->pd_context, &local_timing, 0);
+	} else {
+		ret = port->pd_driver->set_power(port->pd_context, pd_powerstate);
+	}
+
+	if (ret) {
+		EMGD_ERROR_EXIT("PD set_%s returned: 0x%x",
+			(pd_powerstate == PD_POWER_MODE_D0)?"mode":"power", ret);
+		return -IGD_ERROR_INVAL;
+	}
+
+	EMGD_DEBUG("Port_control: 0x%lx", port_control);
+
+	WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, port->port_reg, port_control);
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+
+
+/*!
+ * @param emgd_encoder
+ * @param status
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int kms_post_program_port_tnc(emgd_encoder_t * emgd_encoder,
+	unsigned long status)
+{
+	int ret;
+	struct drm_device  *dev       = NULL;
+	igd_context_t      *context   = NULL;
+	igd_display_port_t *port      = NULL;
+	igd_display_pipe_t *pipe      = NULL;
+	struct drm_encoder *encoder   = NULL;
+	struct drm_crtc    *crtc      = NULL;
+	emgd_crtc_t        *emgd_crtc = NULL;
+	igd_timing_info_t  *timings   = NULL;
+	/* unsigned long portreg; */
+
+	EMGD_TRACE_ENTER;
+
+	encoder = &emgd_encoder->base;
+	dev = encoder->dev;
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+	port = emgd_encoder->igd_port;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (crtc == encoder->crtc) {
+			emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+			pipe = emgd_crtc->igd_pipe;
+			timings = pipe->timing;
+			break;
+		}
+	}
+
+	/*
+	 * The programming found in the common code for all chipsets
+	 * has the device programming sequence as follows:
+	 *  Port
+	 *  Pipe
+	 *  Post Port
+	 *  Plane
+	 * On Gen4, if the port is enabled before the pipe, there is a 10%
+	 * chance that the port will not turn on properly.
+	 * Due to compatability requires with other chipsets, this workaround
+	 * fixes this issue
+	 *
+	 * This is handled by set_power.  This also only seems to apply to a
+	 * chipset that is no longer supported.  Not sure if this will get
+	 * re-introduced with ValleyView and beyond, so I left it here.
+	 *
+	 * portreg = READ_MMIO_REG_TNC(port->port_type, port->port_reg);
+	 * WRITE_MMIO_REG_TNC(port->port_type, port->port_reg, portreg & ~BIT31);
+	 * WRITE_MMIO_REG_TNC(port->port_type, port->port_reg, portreg);
+	 */
+
+	if (port->port_type == IGD_PORT_SDVO) {
+		initialize_ST_bridge(context, port);
+	}
+
+	ret = 0;
+	/* call post_set_mode() if exists */
+	if (port->pd_driver->post_set_mode) {
+		if (port->port_type == IGD_PORT_SDVO){
+			ret = port->pd_driver->post_set_mode(port->pd_context, timings,
+				status); /*Needed for 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/drivers/gpu/drm/emgd/emgd/display/mode/tnc/micro_mode_tnc.c b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/micro_mode_tnc.c
new file mode 100644
index 0000000..f96b710
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/micro_mode_tnc.c
@@ -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 at 60
+	 */
+	return FALSE;
+}
+#endif
+
+/*!
+ *
+ * @param mmio dev2 mmio
+ *
+ * @return void
+ */
+void disable_vga_tnc (unsigned char *mmio)
+{
+	unsigned long temp;
+	unsigned char sr01;
+
+	EMGD_TRACE_ENTER;
+
+	/* Disable VGA plane if it is enabled. */
+	temp = EMGD_READ32(EMGD_MMIO(mmio) + VGACNTRL);
+	if ((temp & BIT31) == 0) {
+		/* Read SR01 */
+		READ_VGA(mmio, SR_PORT, SR01, sr01);
+
+		/* Turn on SR01 bit 5 */
+		WRITE_VGA(mmio, SR_PORT, SR01, sr01|BIT(5));
+
+		/* Wait for 30us */
+		OS_SLEEP(30);
+
+		temp |= BIT31;     /* set bit 31 to disable */
+		temp &= ~BIT30;    /* clear bit 30 to get VGA display in normal size */
+		EMGD_WRITE32(temp, EMGD_MMIO(mmio) + VGACNTRL);
+
+	}
+
+	EMGD_TRACE_EXIT;
+}
+
+/*!
+ *
+ * @param display_handle
+ * @param palette_entry
+ * @param palette_color
+ *
+ * @return 0 on success
+ * @return -IGD_INVAL on failure
+ */
+int igd_set_palette_entry_tnc(
+	igd_display_h display_handle,
+	unsigned long palette_entry,
+	unsigned long palette_color)
+{
+	/* Return if Pipe is not on */
+	if(!((1L<<31) & READ_MMIO_REG_TNC(PORT_TYPE_DH(display_handle),
+			PIPE(display_handle)->pipe_reg))) {
+		return -IGD_INVAL;
+	}
+	/* Palette can is only on 0:2:0 so use _TNC IGD_PORT_LVDS */
+	WRITE_MMIO_REG_TNC(IGD_PORT_LVDS,
+		PIPE(display_handle)->palette_reg + palette_entry * 4,
+		palette_color);
+
+	return 0;
+}
+
+/*!
+ *
+ * @param display_handle
+ * @param palette_entry
+ * @param palette_color
+ *
+ * @return 0 on success
+ * @return -IGD_INVAL on failure
+ */
+int igd_get_palette_entry_tnc(
+	igd_display_h display_handle,
+	unsigned long palette_entry,
+	unsigned long *palette_color)
+{
+	/* Return if Pipe is not on */
+	if(!((1L<<31) & READ_MMIO_REG_TNC(
+			PORT_TYPE_DH(display_handle),
+			PIPE(display_handle)->pipe_reg))) {
+		return -IGD_INVAL;
+	}
+	/* Palette can is only on 0:2:0 so use _TNC IGD_PORT_LVDS */
+	*palette_color = 0xffffff & READ_MMIO_REG_TNC(
+		IGD_PORT_LVDS,
+		PIPE(display_handle)->palette_reg + palette_entry * 4);
+	return 0;
+}
+
+/*!
+ *
+ * @param mmio
+ * @param pipe_reg
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int wait_for_vblank_tnc(unsigned long pipe_reg)
+{
+	unsigned long pipe_status_reg = pipe_reg + PIPE_STATUS_OFFSET;
+	unsigned long tmp;
+	unsigned long port_type = IGD_PORT_LVDS;
+	os_alarm_t timeout;
+	int ret;
+	unsigned long request_for;
+
+	EMGD_TRACE_ENTER;
+
+	EMGD_DEBUG("Parameter: pipe_reg = %lx", pipe_reg);
+
+	/* If pipe is off then just return */
+	if(!((1L<<31) & READ_MMIO_REG_TNC(port_type, pipe_reg))) {
+		EMGD_DEBUG("Pipe disabled/Off");
+		EMGD_TRACE_EXIT;
+		return 1;
+	}
+
+	/*
+	 * When VGA plane is on the normal wait for vblank won't work
+	 * so just skip it. VGA plane is on 0:2:0 so no need to use _TNC macros.
+	 */
+	if(!(EMGD_READ32(MMIO_TNC(port_type) + 0x71400) & 0x80000000)) {
+		EMGD_DEBUG("VGA Plane On");
+		EMGD_TRACE_EXIT;
+		return 1;
+	}
+
+	/* 1. Request the interrupt handler to record the next VBlank: */
+	request_for = VBINT_REQUEST(VBINT_WAIT,
+		(pipe_status_reg == PIPEA_STAT) ? VBINT_PORT4 : VBINT_PORT2);
+	mode_context->dispatch->full->request_vblanks(request_for,
+		MMIO_TNC(port_type));
+
+	/* 2. Wait (about 50 msec, 20Hz) & poll for the next VBlank: */
+	timeout = OS_SET_ALARM(50);
+	do {
+		OS_SCHEDULE();
+		tmp = mode_context->dispatch->full->vblank_occured(request_for);
+	} while ((tmp == 0x00) && (!OS_TEST_ALARM(timeout)));
+
+
+	if (tmp == 0) {
+		EMGD_ERROR_EXIT("Timeout waiting for VBLANK");
+		ret = 0;
+	} else {
+		ret = 1;
+	}
+
+	/* 3. End our request for the next VBlank: */
+	mode_context->dispatch->full->end_request(request_for,
+		MMIO_TNC(port_type));
+
+
+	EMGD_TRACE_EXIT;
+	return ret;
+} /* wait_for_vblank_tnc */
+
+
+
+/*!
+ * This procedure waits for the next vertical blanking (vertical retrace)
+ * period. If the display is already in a vertical blanking period, this
+ * procedure exits.
+ *
+ * Note: A timeout is included to prevent an endless loop.
+ *
+ * @param display_handle
+ *
+ * @return FALSE if timed out
+ */
+int igd_wait_vblank_tnc(igd_display_h display_handle)
+{
+
+	return wait_for_vblank_tnc(PIPE(display_handle)->pipe_reg);
+
+}
+
+
+/*!
+ * Get the stride and stereo values based on the display.  This is also used
+ * by the MI instructions.
+ *
+ * @param display Pointer to hardware device instance data
+ * @param flags Should the stereo be for the frontbuffer or backbuffer?
+ *
+ * @return stride - Stride of the display
+ * @return stereo - Stereo address of the display
+ */
+int mode_get_stride_stereo_tnc(igd_display_context_t *display,
+	unsigned long *stride,
+	unsigned long *stereo,
+	unsigned long flags)
+{
+	unsigned long pitch = PLANE(display)->fb_info->screen_pitch;
+	igd_timing_info_t *timing = PIPE(display)->timing;
+	unsigned long base_offset;
+
+	EMGD_TRACE_ENTER;
+
+	base_offset = PLANE(display)->fb_info->visible_offset;
+	*stride = pitch;
+	*stereo = 0;
+
+	/* For field replication, valid for interlaced modes only
+	 *     set stereo = fb_base
+	 *         stride = pitch
+	 */
+	if (timing->mode_info_flags & IGD_SCAN_INTERLACE) {
+
+		if(timing->mode_info_flags & IGD_LINE_DOUBLE) {
+			/* Interlaced + Line double flags means field replication.
+			 * same lines are sent for both fields. Program the
+			 * second eye to be same as the first
+			 */
+			*stereo = base_offset;
+		} else {
+			/* Regular interlaced. Second eye starts on line 2.
+			 * Skip every other line.
+			 */
+			*stereo = base_offset + pitch;
+			*stride = pitch * 2;
+		}
+	}
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+/*
+ * Atom E6xx LVDS display: Mode switch sequence
+ *
+ * 1. Enable sequence
+ *
+ * Program power on delay, power off delay, power cycle delay registers
+ * Program backlight control register to set appropriate backlight value
+ * Pipe A must be completely off at this point
+ * Write PIPEACONF bits[19:18] = 00
+ * Write DSPACNTR bit[31] = 1
+ * Write DSPASURF = 0x00000000
+ * Write DSPACNTR bit[31] = 0
+ * Write DSPASURF = 0x00000000
+ * Restore PIPEACONF bits[19:18]  to original value
+ * Program DPLL
+ * Enable DPLL
+ * Wait for DPLL warm up 10us and check for DPLL lock bit in Pipe A config reg
+ * (Wait ensures clock is running smoothly before enabling pipe)
+ * Program pipe timings (Can be done before DPLL programming)
+ * Enable panel fitter as needed (Can be done before DPLL and/or
+ *     pipe timing programming)
+ * Enable pipe
+ * Enable planes (VGA or HiRes)
+ * Enable ports
+ * Enable panel power (Can be done before DPLL programming)
+ *
+ * 2. Disable sequence
+ *
+ * Disable panel backlight
+ * Disable panel power (for AOAC standby)
+ * Disable ports
+ * Disable planes (VGA or hires)
+ * Disable pipe
+ * Disable VGA display in 0x71400 bit 31
+ * (Disable VGA display done after disable pipe to allow pipe to turn off
+ *     when no vblank is available in native VGA mode)
+ * Wait for pipe off status
+ * (Wait ensures planes and pipe have completely turned off prior to
+ *     disabling panelfitter then DPLL)
+ * Disable panelfitter
+ * Disable DPLL
+ * Pipe timings change or change between VGA native or VGA center/upperleft
+ *     or HiRes
+ * Use complete disable sequence followed by complete enable sequence with
+ *     new mode programmings.
+ *
+ *
+ * Atom E6xx SDVO display: Display Pipe B Enable/Disable sequence:
+ *
+ * 1. Enable sequence
+ *
+ * Program LNC and LNW DPLL
+ * Write all planes, port, power control registers on both LNC and LNW
+ * 1st Enable LNC pipe
+ * 2nd Enable LNW pipe
+ *
+ * 2. Disable Sequence
+ *
+ * Disable panel power
+ * Disable ports
+ * Disable planes
+ * 1st Disable LNC pipe
+ * 2nd Disable TNC_SDVO pipe
+ * Disable panel fitter
+ * Disable DPLL
+ */
+
+
+/*!
+ *
+ * @param display Pointer to hardware device instance data
+ *
+ * @return void
+ */
+void program_pipe_vga_tnc(
+	igd_display_context_t *display)
+{
+	igd_timing_info_t *timing;
+	unsigned long vga_control;
+	unsigned long upscale = 0;
+	int centering = 1;
+
+	EMGD_TRACE_ENTER;
+
+	/*
+	 * VGA Plane can attach to only one pipe at a time. LVDS can
+	 * only attach to pipe B. We need to use the display passed to
+	 * determine the pipe number to use. (Napa is same as Alm).
+	 */
+
+	/*
+	 * We can come here with following cases:
+	 *   1. magic->vga    CRT, DVI type displays
+	 *   2. native->vga   int-lvds, and up-scaling lvds displays
+	 *   3. pipe->vga     TV and other unscaled-lvds displays
+	 */
+	vga_control = EMGD_READ32(MMIO(display) + 0x71400);
+	vga_control &= 0x18e3ff00;
+	vga_control |= 0x8e;
+
+	timing = PIPE(display)->timing;
+	if(!timing->extn_ptr) {
+		EMGD_ERROR_EXIT("No Extension pointer in program_pipe_vga_tnc");
+		return;
+	}
+
+	/* Find UPSCALING attr value*/
+	pi_pd_find_attr_and_value(PORT_OWNER(display),
+			PD_ATTR_ID_PANEL_FIT,
+			0,/*no PD_FLAG for UPSCALING */
+			NULL, /* dont need the attr ptr*/
+			&upscale);
+	/* this PI func will not modify value of upscale if attr does not exist */
+
+	/* magic->vga || native->vga cases, centering isn't required */
+	if ((timing->width == 720 && timing->height == 400) || upscale) {
+		EMGD_DEBUG("Centering = 0");
+		centering = 0;
+	}
+
+	/* Enable border */
+	if((timing->width >= 800) && !upscale) {
+		EMGD_DEBUG("Enable VGA Border");
+		vga_control |= (1L<<26);
+	}
+
+	if(timing->width == 640) {
+		EMGD_DEBUG("Enable Nine Dot Disable");
+		vga_control |= (1L<<18);
+	}
+
+	if(centering) {
+		EMGD_DEBUG("Enable VGA Center Centering");
+		vga_control |= 1L<<24;
+
+		if(timing->height >= 960) {
+			if(timing->width >= 1280) {
+				EMGD_DEBUG("Enable VGA 2x (Nine Dot Disable)");
+				vga_control |= (1L<<30) | (1L<<18);
+			}
+		}
+	} else {
+		if(PORT_OWNER(display)->port_type == IGD_PORT_LVDS) {
+			EMGD_DEBUG("Enable VGA Upper-Left Centering & Nine Dot Disable");
+			vga_control |= (1L<<25 | (1L<<18));
+		} else if (upscale) {
+			EMGD_DEBUG("Enable VGA Center Upper-left for upscale ports");
+			vga_control |= 1L<<25;
+		}
+	}
+
+	if(PIPE(display)->pipe_num) {
+		vga_control |= 1L<<29;
+	}
+
+	program_pipe_vga(display, (igd_timing_info_t *)timing->extn_ptr);
+	EMGD_WRITE32(vga_control, MMIO(display) + 0x71400);
+
+	EMGD_TRACE_EXIT;
+	return;
+}
+
+
+#ifndef CONFIG_MICRO
+extern os_pci_dev_t bridge_dev;
+int read_bunit_tnc(unsigned long reg, unsigned long *val)
+{
+	reg <<= 8;
+	reg &= 0x0000ff00;
+	reg |= 0xD00300F0;
+  	 
+	EMGD_TRACE_ENTER;
+  	 
+	if(OS_PCI_WRITE_CONFIG_32(bridge_dev, 0xD0, reg)) {
+		EMGD_ERROR_EXIT("Writing into the MCR Failed\n");
+		return -IGD_ERROR_INVAL;
+	}
+  	 
+	if(OS_PCI_READ_CONFIG_32(bridge_dev, 0xD4, val)) {
+		EMGD_ERROR_EXIT("Reading from MDR Failed\n");
+		return -IGD_ERROR_INVAL;
+	}
+  	 
+	EMGD_TRACE_EXIT;
+  	 
+	return 0;
+}
+  	 
+int write_bunit_tnc(unsigned long reg, unsigned long val)
+{
+	reg <<= 8;
+	reg &= 0x0000ff00;
+	reg |= 0xE00300F0;
+  	 
+	EMGD_TRACE_ENTER;
+  	 
+	if(OS_PCI_WRITE_CONFIG_32(bridge_dev, 0xD4, val)) {
+			EMGD_ERROR_EXIT("Writing into the MDR Failed\n");
+		return -IGD_ERROR_INVAL;
+	}
+  	 
+	if(OS_PCI_WRITE_CONFIG_32(bridge_dev, 0xD0, reg)) {
+		EMGD_ERROR_EXIT("Writing into the MCR Failed\n");
+		return -IGD_ERROR_INVAL;
+	}
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+#endif
+
+/*!
+ * Program Display Plane Values.
+ *
+ * @param display Pointer to hardware device instance data
+ * @param status
+ *
+ * @return void
+ */
+void program_plane_tnc(igd_display_context_t *display,
+	unsigned long status)
+{
+	unsigned long stride;
+	unsigned long stereo;
+	unsigned long plane_control;
+	unsigned long other_plane_reg;
+	igd_timing_info_t *timing;
+	igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info;
+	unsigned long plane_reg = PLANE(display)->plane_reg;
+	igd_timing_info_t *pipe_timing;
+#ifndef  CONFIG_MICRO
+	unsigned long ulreg = 0;
+#endif
+	unsigned long b_reg;
+	/* tnc_wa_timing_t *wa = WA_TUNE; */
+
+	EMGD_TRACE_ENTER;
+
+	EMGD_DEBUG("Program Plane: %s", status?"ENABLE":"DISABLE");
+	EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display));
+
+	igd_wait_vblank_tnc((igd_display_h)display);
+
+	plane_control = EMGD_READ32(MMIO(display) + plane_reg);
+	if(PLANE(display)->plane_reg == DSPACNTR) {
+		plane_control &= device_data_tnc->plane_a_preserve;
+	} else { /* if it's plane b or plane c */
+		plane_control &= device_data_tnc->plane_b_c_preserve;
+	}
+
+	/* TODO: Bspec: For EagleLake this Trickle Feed must always disable */
+
+	if((status == FALSE) ||
+		(GET_DEVICE_POWER_STATE(display) != IGD_POWERSTATE_D0)) {
+
+		/*
+		 * Note: The vga programming code does not have an "off". So
+		 * when programming the plane to off we make sure VGA is off
+		 * as well.
+		 */
+		disable_vga_tnc(MMIO(display));
+
+		/*
+		 * To turn off plane A or B, the program have to triger the plane A or B
+		 * start register.  Or else, it will not work.
+		 */
+		EMGD_WRITE32(plane_control, MMIO(display) + plane_reg);
+		EMGD_WRITE32(EMGD_READ32(MMIO(display) + plane_reg + DSP_START_OFFSET),
+			MMIO(display) + plane_reg + DSP_START_OFFSET);
+
+		igd_wait_vblank_tnc((igd_display_h)display);
+		EMGD_TRACE_EXIT;
+		return;
+	}
+	/*
+	 * Note: The very first pass through this function will be with
+	 * status false and timings == NULL. Don't use the timings before
+	 * the check above.
+	 */
+	timing = PIPE(display)->timing;
+	pipe_timing = timing;
+	/* There is a special case code for legacy VGA modes */
+	while (timing->extn_ptr) {
+		timing = (igd_timing_info_t *)timing->extn_ptr;
+	}
+	if(MODE_IS_VGA(timing) && CHECK_VGA(pipe_timing)) {
+		program_plane_vga(display, timing);
+		EMGD_TRACE_EXIT;
+		return;
+	}
+
+	disable_vga_tnc(MMIO(display));
+
+	/* enable plane, select pipe, enable gamma correction logic */
+	plane_control |= 0x80000000 | (PIPE(display)->pipe_num<<24);
+	PIPE(display)->plane = PLANE(display);
+#ifndef CONFIG_MICRO
+	plane_control |= (1<<30);
+#endif
+
+	/* Here the settings:
+	 *   If line + pixel dbling, set 21,20 to 01b, and set Horz Multiply
+	 *   If line dbling only,    set 21,20 to 11b
+	 *   If pixel dbling only,   set 21,20 to 00b, but set Horz Multiply
+	 *   If no doubling,         set 21,20 to 00b (no Horz Multiply)
+	 * For pixel doubling
+	 *           --> both progressive/interlaced modes
+	 * For Line doubling
+	 *           --> progressive modes only
+	 */
+
+	if (!(timing->mode_info_flags & IGD_SCAN_INTERLACE)) {
+		/* Line doubling in progressive mode requires special bits */
+		if (timing->mode_info_flags & IGD_LINE_DOUBLE) {
+			/* BIT 20 for line & pixel doubling*/
+			plane_control |= BIT20;
+			/* check later, if no pixel doubling, set bit 21 too*/
+		}
+	}
+	if (timing->mode_info_flags & IGD_PIXEL_DOUBLE) {
+		/* For line ONLY doubling, set bit 21 also '1' */
+		plane_control |= BIT21;
+	}
+
+	mode_get_stride_stereo_tnc(display, &stride, &stereo, 0);
+
+	/* set color depth */
+	switch (IGD_PF_DEPTH(fb_info->pixel_format)) {
+	case PF_DEPTH_8:
+		plane_control |= BIT27 | BIT30;
+		break;
+	case PF_DEPTH_16:
+		plane_control |= BIT28 | BIT26;
+		break;
+	default:
+	case PF_DEPTH_32:
+		plane_control |= BIT28 | BIT27;
+		break;
+	}
+
+	if(fb_info->flags & IGD_ENABLE_DISPLAY_GAMMA) {
+		plane_control |= (BIT30);
+	}
+
+	if(fb_info->flags & IGD_SURFACE_TILED) {
+		plane_control |= (BIT10);
+	}
+
+	/* Set watermark for Atom E6xx */
+#ifndef  CONFIG_MICRO
+	if (!mode_context->en_reg_override) {
+		if (plane_reg == DSPACNTR) {
+			other_plane_reg = DSPBCNTR;
+		} else {
+			other_plane_reg = DSPACNTR;
+		}
+
+		if (EMGD_READ32(MMIO(display) + other_plane_reg) & 0x80000000) {
+			EMGD_WRITE32(device_data_tnc->dsp_arb, MMIO(display) +
+				PIPEA_DISP_ARB_CTRL);
+		} else if (plane_reg == DSPACNTR) {
+			EMGD_WRITE32(0x00003fff, MMIO(display) + PIPEA_DISP_ARB_CTRL);
+		} else {
+			EMGD_WRITE32(0x00003f80, MMIO(display) + PIPEA_DISP_ARB_CTRL);
+		}
+
+		/*
+		 * Setting WM priority level to 11
+		 * to workaround display bouncing issues
+		 * TODO: Mode set from Clone->Single(Primary)
+		 * PIPEA_DISP_ARB_CTRL does not get updated
+		 */
+		ulreg = EMGD_READ32(MMIO(display) + 0x00020f8);
+		EMGD_WRITE32(ulreg | 0x000003f0, MMIO(display) + 0x00020f8);
+
+		EMGD_WRITE32(device_data_tnc->fifo_watermark1, MMIO(display) + FW_1);
+		EMGD_WRITE32(device_data_tnc->fifo_watermark2, MMIO(display) + FW_2);
+		EMGD_WRITE32(device_data_tnc->fifo_watermark3, MMIO(display) + FW_3);
+		EMGD_WRITE32(device_data_tnc->fifo_watermark4, MMIO(display) + FW_4);
+		EMGD_WRITE32(device_data_tnc->fifo_watermark5, MMIO(display) + FW_5);
+		EMGD_WRITE32(device_data_tnc->fifo_watermark6, MMIO(display) + FW_6);
+	} else {
+		/* en_reg_override=1 */
+		/* Override display registers */
+		EMGD_WRITE32(mode_context->gvd_hp_control, MMIO(display) + 0x00020f8);
+		EMGD_WRITE32(mode_context->disp_arb, MMIO(display) + PIPEA_DISP_ARB_CTRL);
+		EMGD_WRITE32(mode_context->fifo_watermark1, MMIO(display) + FW_1);
+		EMGD_WRITE32(mode_context->fifo_watermark2, MMIO(display) + FW_2);
+		EMGD_WRITE32(mode_context->fifo_watermark3, MMIO(display) + FW_3);
+		EMGD_WRITE32(mode_context->fifo_watermark4, MMIO(display) + FW_4);
+		EMGD_WRITE32(mode_context->fifo_watermark5, MMIO(display) + FW_5);
+		EMGD_WRITE32(mode_context->fifo_watermark6, MMIO(display) + FW_6);
+		EMGD_WRITE32(mode_context->disp_chicken_bits, MMIO(display) + 0x0070400);
+
+		/* Override Bunit Chickenbits and BWFLUSH register */
+		write_bunit_tnc(0x30, mode_context->bunit_chicken_bits);
+		write_bunit_tnc(0x02, mode_context->bunit_write_flush);
+	}
+
+	EMGD_DEBUG(" GVD HP_CONTROL: 0x%lx", ulreg);
+	ulreg = EMGD_READ32(MMIO(display) + PIPEA_DISP_ARB_CTRL);
+	EMGD_DEBUG(" Display Arbitration register: 0x%lx", ulreg);
+	ulreg = EMGD_READ32(MMIO(display) + FW_1);
+	EMGD_DEBUG(" FIFO Watermark Control Register 1: 0x%lx", ulreg);
+	ulreg = EMGD_READ32(MMIO(display) + FW_2);
+	EMGD_DEBUG(" FIFO Watermark Control Register 2: 0x%lx", ulreg);
+	ulreg = EMGD_READ32(MMIO(display) + FW_3);
+	EMGD_DEBUG(" FIFO Watermark Control Register 3: 0x%lx", ulreg);
+	ulreg = EMGD_READ32(MMIO(display) + FW_4);
+	EMGD_DEBUG(" FIFO Watermark Control Register 4: 0x%lx", ulreg);
+	ulreg = EMGD_READ32(MMIO(display) + FW_5);
+	EMGD_DEBUG(" FIFO Watermark Control Register 5: 0x%lx", ulreg);
+	ulreg = EMGD_READ32(MMIO(display) + FW_6);
+	EMGD_DEBUG(" FIFO Watermark Control Register 6: 0x%lx", ulreg);
+	ulreg = EMGD_READ32(MMIO(display) + DSP_CHICKENBITS);
+	EMGD_DEBUG(" Display Chicken bits: 0x%lx", ulreg);
+	read_bunit_tnc(0x30, &b_reg);
+	EMGD_DEBUG(" Bunit Chicken bits: 0x%lx", b_reg);
+	read_bunit_tnc(0x02, &b_reg);
+	EMGD_DEBUG(" Bunit Write Flush: 0x%lx", b_reg);
+#else
+	/* ITP Script is doing this and so go ahead */
+	/* The PIPEA_DISP_ARB_CTRL set fixed the issue with 32bit vesa modes */
+	EMGD_WRITE32(0x00001FBF, MMIO(display) + PIPEA_DISP_ARB_CTRL);
+	EMGD_WRITE32(0x3F8F0F18, MMIO(display) + FW_1);
+#endif
+	/* FIXME: Not required for TNC.
+	 * The B-Spec states that rendering will be slower if the fences are not
+	 * a power of 2.  So for now, always use a power of 2. */
+	/* EMGD_WRITE32(0x04000400, MMIO(display) + 0x209c); */
+
+	EMGD_DEBUG(" Plane Control: 0x%lx", plane_control);
+	EMGD_DEBUG(" Plane Base:    0x%lx", fb_info->visible_offset);
+	EMGD_DEBUG(" Plane Pitch:   0x%lx", stride);
+
+	EMGD_WRITE32(plane_control, MMIO(display) + plane_reg);
+	EMGD_WRITE32(stride, MMIO(display) + plane_reg + DSP_STRIDE_OFFSET);
+	/* Both of these registers are Reserved on Gen4 */
+	/*EMGD_WRITE32(size, MMIO(display) + plane_reg + DSP_SIZE_OFFSET);*/
+	/*EMGD_WRITE32(stereo, MMIO(display) + plane_reg + DSP_STEREO_OFFSET);*/
+	EMGD_WRITE32(0, MMIO(display) + plane_reg + DSP_LINEAR_OFFSET);
+	EMGD_WRITE32(0, MMIO(display) + plane_reg + 0x24);
+	EMGD_WRITE32(fb_info->visible_offset,
+		MMIO(display) + plane_reg + DSP_START_OFFSET);
+
+	igd_wait_vblank_tnc((igd_display_h)display);
+
+	EMGD_TRACE_EXIT;
+}
+
+/*!
+ * PGen4 can check when the pipe is enabled or disabled.
+ * This function waits for the pipe to be enabled or disabled.
+ * check_on_off = 0 to wait for the pipe to disable.
+ * check_on_off = 0x40000000 to wait for the pipe to enable.
+ *
+ * @param mmio
+ * @param pipe_reg
+ * @param check_on_off
+ *
+ * @return void
+ */
+void wait_pipe(unsigned long pt, unsigned long pipe_reg, unsigned long check_on_off)
+{
+	unsigned long temp;
+	os_alarm_t timeout;
+
+	EMGD_TRACE_ENTER;
+
+	/* 0:3:0 doesn't wait pipe, only LNC device does. */
+	if (pt == IGD_PORT_SDVO) {
+		return;
+	}
+
+	/* Wait for Pipe enable/disable, about 50 msec (20Hz). */
+	timeout = OS_SET_ALARM(50);
+	do {
+		OS_SCHEDULE();
+		temp = EMGD_READ32(MMIO_TNC(IGD_PORT_LVDS) + pipe_reg) & 0x40000000;
+		/* Check for timeout */
+	} while ((temp != check_on_off) && (!OS_TEST_ALARM(timeout)));
+
+	if (temp != check_on_off) {
+		EMGD_ERROR_EXIT("Timeout waiting for pipe enable/disable");
+	}
+
+	EMGD_TRACE_EXIT;
+	return;
+}
+
+unsigned long get_port_type(int crtc_id) {
+	if (crtc_id == IGD_KMS_PIPEA) {
+		return IGD_PORT_LVDS;
+	}
+	if (crtc_id == IGD_KMS_PIPEB) {
+		return IGD_PORT_SDVO;
+	}
+	EMGD_ERROR("Unrecognized port type based on crtc_id of %d", crtc_id);
+	return 0;
+}
+
+/*!
+ * This function programs the Timing registers and clock registers and
+ * other control registers for PIPE.
+ *
+ * @param display
+ * @param status
+ *
+ * @return void
+ */
+void program_pipe_tnc(igd_display_context_t *display,
+	unsigned long status)
+{
+	unsigned long   timing_reg;
+	unsigned long   pipe_conf;
+	unsigned long   hactive, vactive;
+	igd_timing_info_t  *pTimings;
+	igd_timing_info_t  pTimings_tmp;
+	igd_display_port_t *port;
+	unsigned long temp;
+	unsigned long pt = PORT_TYPE(display);
+	unsigned long dc;
+	unsigned long calc;
+	short hactive_tmp, vactive_tmp;
+	int i;
+	tnc_wa_timing_t *wa;
+	/* igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info; */
+	platform_context_tnc_t *platform_context;
+
+	EMGD_TRACE_ENTER;
+
+	EMGD_DEBUG("Program Pipe: %s", status?"ENABLE":"DISABLE");
+	EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display));
+
+	platform_context = (platform_context_tnc_t *)display->context->platform_context;
+
+	/* For Windows OS, flag_clip_fix will be overridden by configurable parameter in registry.
+	* This section of code is excluded in VBIOS, VBIOS will always use the pre-assigned value.
+	*/
+	flag_clip_fix = mode_context->clip_hw_fix;
+
+	pipe_conf = device_data_tnc->pipe_preserve &
+		READ_MMIO_REG_TNC(pt, PIPE(display)->pipe_reg);
+
+	if((status == FALSE) ||
+		(GET_DEVICE_POWER_STATE(display) == IGD_POWERSTATE_D3)) {
+		/* For SDVO disable both pipe Bs in 0:2:0 and 0:3:0 */
+		if (pt == IGD_PORT_SDVO) {
+			WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PIPE(display)->pipe_reg,
+				pipe_conf & (~0x80000000L));
+			/* After disable pipe B in 0:2:0, wait_pipe must be
+ 			 * called to ensure the pipe B to be turned off */
+			wait_pipe(IGD_PORT_LVDS, PIPE(display)->pipe_reg, 0);
+		}
+		/* Disable pipe */
+		WRITE_MMIO_REG_TNC(pt, PIPE(display)->pipe_reg,
+			pipe_conf & (~0x80000000L));
+
+		/* check when the pipe is disabled. */
+		wait_pipe(pt, PIPE(display)->pipe_reg, 0);
+
+		/* Disable DPLL */
+		//WRITE_MMIO_REG_TNC(pt, PIPE(display)->clock_reg->dpll_control,
+		//	READ_MMIO_REG_TNC(pt,
+		//		PIPE(display)->clock_reg->dpll_control) & ~0x80000000L);
+
+		EMGD_TRACE_EXIT;
+		return;
+	}
+
+	/* For TNC B1, enable hardware cliping fix*/
+	if((platform_context->tnc_dev3_rid == TNC_B1_DEV3_RID)&&
+		(flag_clip_fix & IGD_CLIP_FIX_GLOBAL_ENABLE)) {
+			/* Disable SDVO Pipe in Device 2 and Device 3 */
+			WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PIPE(display)->pipe_reg,
+				pipe_conf & (~0x80000000L));
+  	 
+			WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, PIPE(display)->pipe_reg,
+				pipe_conf & (~0x80000000L));
+ 
+			/* check when the pipe is disabled. */
+			wait_pipe(IGD_PORT_LVDS, PIPE(display)->pipe_reg, 0);
+  	 
+			/* Enable clipping hardware fix */
+			temp = READ_MMIO_REG_TNC(IGD_PORT_LVDS, DSP_CHICKENBITS);
+			if(flag_clip_fix & IGD_CLIP_FIX_REPLACE_STALL) {
+				temp |= BIT18;
+			} else {
+				temp &= ~BIT18;
+			}
+			if(flag_clip_fix & IGD_CLIP_FIX_DISABLE_THROTTLE) {
+				temp |= BIT15;
+			} else {
+				temp &= ~BIT15; 
+			}
+			WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, DSP_CHICKENBITS, temp);
+	}
+
+
+	port     = PORT_OWNER(display);
+	pTimings = PIPE(display)->timing;
+
+	{
+		/* Debug messages */
+		pd_timing_t *vga_timing = (pd_timing_t *)pTimings->extn_ptr;
+		EMGD_DEBUG("pTimings %ux%u mode_number = %u mode_info_flags = 0x%lx, dclk = %lu",
+			pTimings->width,
+			pTimings->height,
+			pTimings->mode_number,
+			pTimings->mode_info_flags,
+			pTimings->dclk);
+		if (vga_timing) {
+			EMGD_DEBUG("ext_timing %ux%u mode_number = %u mode_info_flags= 0x%lx, dclk = %lu",
+				vga_timing->width,
+				vga_timing->height,
+				vga_timing->mode_number,
+				vga_timing->mode_info_flags,
+				vga_timing->dclk);
+		}
+	}
+
+	/*
+	 * If the mode is VGA and the PD says it handles all VGA modes without
+	 * reprogramming then just set the mode and leave centering off.
+	 */
+	if(pTimings->mode_info_flags & IGD_MODE_VESA) {
+			EMGD_DEBUG("IGD_MODE_VESA");
+		if (pTimings->mode_number <= VGA_MODE_NUM_MAX) {
+			/* Pipe timings and clocks no longer need to be set since
+			 * the VGA timings will be used.
+			WRITE_MMIO_REG_TNC(pt, PIPE(display)->pipe_reg,
+				pipe_conf | 0x80000000); */
+
+			/* Gen4 can check when the pipe is enabled. No longer needed
+			 * since pipe not enabled and VGA timings are used.
+			wait_pipe(PIPE(display)->pipe_reg, 0x40000000);*/
+
+			EMGD_DEBUG("pTimings->mode_number <= VGA_MODE_NUM_MAX");
+			program_pipe_vga_tnc(display);
+			EMGD_TRACE_EXIT;
+			return;
+		} else {
+#ifdef CONFIG_MICRO
+			set_256_palette(
+				MMIO_TNC(PORT(display, display->port_number)->port_type));
+#endif
+		}
+	}
+
+	/* Program dot clock divisors. */
+	program_clock_tnc(display, PIPE(display)->clock_reg, pTimings->dclk);
+
+	/* Program timing registers for the pipe */
+	timing_reg = PIPE(display)->timing_reg;
+	if (pTimings->mode_info_flags & IGD_PIXEL_DOUBLE) {
+		hactive = (unsigned long)pTimings->width*2 - 1;
+	} else {
+		hactive = (unsigned long)pTimings->width - 1;
+	}
+
+	if (pTimings->mode_info_flags & IGD_LINE_DOUBLE) {
+		vactive = (unsigned long)pTimings->height*2 - 1;
+	} else {
+		/* For Atom E6xx Hardware will automatically divide by 2 to
+		   get the number of line in each field */
+		vactive = (unsigned long)pTimings->height - 1;
+	}
+
+#ifndef CONFIG_MICRO
+	/* reset the palette */
+	for (i = 0; i < 256; i++) {
+		WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PIPE(display)->palette_reg,
+			((i<<16) | (i<<8) | i));
+	}
+
+
+	/* apply color correction */
+	for( i = 0; PD_ATTR_LIST_END != port->attributes[i].id; i++ ) {
+
+		if ((PD_ATTR_ID_FB_GAMMA      == (port->attributes[i].id)) ||
+			(PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)) ||
+			(PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)))  {
+
+			mode_context->dispatch->full->set_color_correct(display);
+		}
+	}
+#endif
+
+	/*
+	 * NOTE: For size reasons the timng table contains unsigned short
+	 * values. Don't shift them past 16. Use a temp instead.
+	 * All register offsets and bit shift are verified for Gen4
+	 *
+	 * For SDVO display:
+	 * Write values into pipe B registers in both 0:2:0 and 0:3:0
+	 */
+
+	dc = *(display->context->mod_dispatch.dsp_current_dc);
+
+	wa = WA_TUNE;
+
+	for (i=0; i<2; i++) {
+		/* Temp variable */
+		pTimings_tmp = *pTimings;
+		hactive_tmp = (short) hactive;
+		vactive_tmp = (short) vactive;
+#ifndef CONFIG_MICRO
+
+		/* Htotal and tuning wa is not supported in VBIOS for TNC				
+		 * TNC B0: Enable Htotal formula and CRC Tuning to fix clipping issue and
+		 * async flip flikering on single display
+		 * TNC B1: Enable Htotal formula without CRC Tuning to fix async flip flikering
+		 * For B0, TVOUT is excluded for htotal workaround to avoid image shifting 
+		 * issue happen. Image shifting will be fixed on B1 while ref_freq is lower down
+		 * to 198Mhz
+		 */
+
+
+		if(	(pt == IGD_PORT_SDVO) && FLAG(flag_basic_htotal_formula_wa) &&
+			(   ((platform_context->tnc_dev3_rid == TNC_B1_DEV3_RID) && 
+					(mode_context->async_flip_wa)	)||
+				(   (platform_context->tnc_dev3_rid == TNC_B0_DEV3_RID) &&
+				    (!IGD_DC_SINGLE(dc) || (port->pd_driver->type != PD_DISPLAY_TVOUT))
+				)
+			)){
+
+
+	 		if((!(pTimings->reserved_dd & TNC_HTOTAL_TUNED)) &&
+	 				(wa->counter < LIMIT_TOTAL_CHECK_DISPLAY) &&
+					(platform_context->tnc_dev3_rid == TNC_B0_DEV3_RID) &&
+ 					(FLAG(flag_enable_tuning_wa))) {
+
+				/* Modify blanks so it always begin after active pixel and ends at the
+				 * end. Do not change it if we are already tuned to maintain
+				 * original timing specification
+				 */
+				pTimings_tmp.hblank_start = (short) (pTimings->width - 1);
+				pTimings_tmp.vblank_start = (short) (pTimings->height - 1);
+				pTimings_tmp.hblank_end = (short) (pTimings->htotal);
+				pTimings_tmp.vblank_end = (short) (pTimings->vtotal);
+			}
+
+#ifndef CONFIG_MICRO
+			/* Delay Frame start while Tuning*/
+			/* Frame start delay is added as plane corruption occurs without delay. 
+			 * Pipe would begin fetching data from random memory location causing the delay. 
+			 * Silicon could not determine why this is happening but agree that adding a delay 
+			 * would not cause any issue unless for a DTD with single vsync line which is 
+			 * super unlikely used.
+			 */
+
+			/* B1 stepping does not need to set this bit because it does not need tuning*/
+			if((platform_context->tnc_dev3_rid == TNC_B0_DEV3_RID) && 
+				(IGD_DC_CLONE(dc) || IGD_DC_EXTENDED(dc))){
+				pipe_conf |= BIT27;
+			}
+#endif
+
+
+			if(i==0){
+				if(pTimings->reserved_dd == 0 || (wa->counter > LIMIT_TOTAL_CHECK_DISPLAY)){
+					/* First time tuning */
+					if ((mode_context->ref_freq != 0) && 
+							(mode_context->ref_freq >= 190000) && 
+							(mode_context->ref_freq <= 210000))
+					{
+						if ((platform_context->tnc_dev3_rid == TNC_B1_DEV3_RID)){
+							/* The optimum reference frequency used for 3DMark flickering workaround formula
+							is the LNC clock minus the optimum margin found from experiment */
+							calc = (pTimings->htotal * (mode_context->ref_freq - LNC_B1_OPTIMUM_MARGIN));
+						} else {
+						calc = (pTimings->htotal * mode_context->ref_freq);
+						}
+					} else {
+						if((platform_context->tnc_dev3_rid == TNC_B1_DEV3_RID)){
+							calc = (pTimings->htotal * (LNC_CLOCK - LNC_B1_OPTIMUM_MARGIN));
+					} else {
+						calc = (pTimings->htotal * LNC_CLOCK);
+						}
+
+					}
+
+					calc = (calc / (PIPE(display)->clock_reg->actual_dclk));
+					calc *= (pTimings->vtotal -1);
+					calc /= pTimings->vtotal;
+					pTimings_tmp.htotal = (short)calc;
+					pTimings->reserved_dd = wa->htotal = pTimings_tmp.htotal;
+					EMGD_DEBUG("Delta = %d", wa->htotal);
+				}else if (pTimings->reserved_dd & TNC_HTOTAL_TUNED){
+					pTimings_tmp.htotal = (short)(pTimings->reserved_dd & (~TNC_HTOTAL_TUNED));
+				}else{
+					if(wa->htotal == 0)
+						wa->htotal = (short)pTimings->reserved_dd;
+					pTimings_tmp.htotal = wa->htotal;
+				}
+				/* Use vphase formula if available */
+				if(vphase){
+					pTimings_tmp.vtotal -= (short)vphase;
+					pTimings_tmp.vsync_start -= (short)vphase;
+					pTimings_tmp.vsync_end -= (short)vphase;
+					pTimings_tmp.vblank_end -= (short)vphase;
+				}else{
+					//pTimings_tmp.hblank_start += (short) (pTimings_tmp.htotal - pTimings->htotal);
+					pTimings_tmp.hblank_end += (short) (pTimings_tmp.htotal - pTimings->htotal);
+				}
+			}
+		}
+#endif
+
+		temp = (unsigned long)(pTimings_tmp.htotal) << 16 | hactive_tmp;
+		WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg, temp);
+
+		temp = ((unsigned long) pTimings_tmp.hblank_end << 16) |
+			(unsigned long)(pTimings_tmp.hblank_start);
+		WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x04, temp);
+
+		temp = ((unsigned long)(pTimings->hsync_end) << 16) |
+			(unsigned long)(pTimings->hsync_start);
+		WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x08, temp);
+
+		temp = ((unsigned long)(pTimings_tmp.vtotal) << 16) | vactive_tmp;
+		WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x0C, temp);
+
+		temp = ((unsigned long)(pTimings_tmp.vblank_end) << 16) |
+			(unsigned long)(pTimings_tmp.vblank_start);
+		WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x10, temp);
+
+		temp = ((unsigned long)(pTimings_tmp.vsync_end)<< 16) |
+			(unsigned long)(pTimings_tmp.vsync_start);
+		WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x14, temp);
+
+		/*
+		 * If there is a linked mode it is either the VGA or a scaled
+		 * mode. If it is scaled then we need to use it as the source size.
+		 */
+		if(pTimings->extn_ptr) {
+			igd_timing_info_t *scaled_timings =
+				(igd_timing_info_t *)pTimings->extn_ptr;
+			if((scaled_timings->mode_info_flags & IGD_MODE_VESA) &&
+				(scaled_timings->mode_number <= VGA_MODE_NUM_MAX)) {
+				temp = (hactive << 16) | vactive;
+			} else {
+				EMGD_DEBUG("scaled_timings->width [%d], scaled_timings->height [%d]\n", scaled_timings->width, scaled_timings->height);
+				temp = (unsigned long)scaled_timings->width  - 1;
+				temp = (temp << 16) |
+					(unsigned long)(scaled_timings->height - 1);
+			}
+		} else {
+			temp = (hactive_tmp << 16) | vactive_tmp;
+		}
+		WRITE_MMIO_REG_TNC(ports_tnc[i], timing_reg + 0x1C, temp);
+
+		/* Enable pipe */
+		pipe_conf |= PIPE_ENABLE;
+
+		/* Put pipe in interlaced mode if requested:
+		 *     should only happen for LVDS display if at all. */
+		if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) {
+			pipe_conf |= (INTERLACE_EN);
+		} else {
+			pipe_conf &= ~(INTERLACE_EN);
+		}
+
+#ifdef CONFIG_MICRO
+		if (pt == IGD_PORT_SDVO) {
+			/*
+			   Enable the panel fitter as VGA controller in Lincroft
+			   is a Panel Fitted VGA controller.
+			   LNC only supports panel fitted VGA mode
+			   (upper left VGA mode). You need to enable the panel fitter.
+			   The timing control will be from the pipe timing generator
+			   but not from the VGA timing generator CRTC registers
+			   as in the centering mode.
+			*/
+			WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, PFIT_CONTROL, 0xA2000000);
+		}
+#endif
+
+		WRITE_MMIO_REG_TNC(ports_tnc[i], PIPE(display)->pipe_reg, pipe_conf);
+		WRITE_MMIO_REG_TNC(ports_tnc[i], PIPE(display)->pipe_reg, pipe_conf);
+		/* For LVDS port, don't touch dev3 registers stop after 1st iteration */
+		if (pt == IGD_PORT_LVDS) {
+			break;
+		}
+	}
+
+
+	/* Gen4 can check when the pipe is enabled. */
+	wait_pipe(IGD_PORT_LVDS, PIPE(display)->pipe_reg, 0x40000000);
+
+	/*
+	 * Set the VGA address range to 0xa0000 so that a normal (not VGA)
+	 * mode can be accessed through 0xa0000 in a 16bit world.
+	 */
+	WRITE_AR(MMIO(display), 0x10, 0xb);
+	WRITE_VGA(MMIO(display), GR_PORT, 0x06, 0x5);
+	WRITE_VGA(MMIO(display), GR_PORT, 0x10, 0x1);
+
+	if(pTimings->extn_ptr) {
+		/* This means either internal scaling (LVDS) or centered VGA */
+		pTimings = pTimings->extn_ptr;
+		if(pTimings->extn_ptr) {
+			/* This is both the scaled and centered VGA */
+			pTimings = pTimings->extn_ptr;
+		}
+		if (pTimings->mode_info_flags & IGD_MODE_VESA) {
+			if (pTimings->mode_number <= VGA_MODE_NUM_MAX) {
+				program_pipe_vga_tnc(display);
+			} else {
+#ifdef CONFIG_MICRO
+				/*
+				 * FIXME: This is not appropriate. This assumes that
+				 * CONFIG_MICRO means "This is vBIOS" and programs
+				 * the palette. vBIOS IAL should probably just set the
+				 * palette itself??
+				 */
+				set_256_palette(
+					MMIO_TNC(PORT(display, display->port_number)->port_type));
+#endif
+			}
+		}
+	}
+
+	if (pt == IGD_PORT_SDVO) {
+		/*  Enable Chicken Bit */
+		/*  Setting BIT6 enable Pipe B Palette Write
+         *  to prevent hang during palette write */
+		/*  Enable Chicken Bit */
+		temp = READ_MMIO_REG_TNC(IGD_PORT_LVDS, DSP_CHICKENBITS);
+		WRITE_MMIO_REG_TNC(IGD_PORT_LVDS, DSP_CHICKENBITS, temp | BIT6);
+	}
+
+	EMGD_TRACE_EXIT;
+	return;
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+void reset_plane_pipe_ports_tnc(igd_context_t *context)
+{
+	igd_plane_t *plane;
+	igd_display_pipe_t *pipe;
+	igd_display_port_t *port,*tv_port=NULL;
+	unsigned long temp;
+	unsigned long i, j;
+	unsigned char *mmio;
+	inter_module_dispatch_t *md;
+
+	EMGD_TRACE_ENTER;
+
+	/*
+	 * Disable all plane, pipe and port registers because the
+	 * bios may have been using a different set. Only unset the
+	 * enable bit.
+ */
+	mmio = EMGD_MMIO(context->device_context.virt_mmadr);
+	md = &context->mod_dispatch;
+	/* Turn off LVDS and SDVO ports */
+	port = NULL;
+	while((port = md->dsp_get_next_port(context, port, 0)) != NULL) {
+		/* if the port is TV, then don't set the power to S3 as this causes
+		 * blank screen on analog port after killx or cosole mode,
+		 * probably because the external clock needs to be on till the pipes and
+		 * DPLLs are off
+		 */
+		if (port->pd_driver) {
+			if(port->pd_type == PD_DISPLAY_TVOUT) {
+				tv_port = port;
+			}else {
+				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/drivers/gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.c b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.c
new file mode 100644
index 0000000..2f22ef6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.c
@@ -0,0 +1,2074 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mode_tnc.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.
+ *
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF 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++;
+	}
+
+
+	/* 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--;
+		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/drivers/gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.h b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.h
new file mode 100644
index 0000000..98d667e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/mode/tnc/mode_tnc.h
@@ -0,0 +1,52 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mode_tnc.h
+ * $Revision: 1.2 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2011, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.mode
+
+typedef struct _mode_data_tnc {
+	unsigned long plane_a_preserve;
+	unsigned long plane_b_c_preserve;
+	unsigned long pipe_preserve;
+	unsigned long dsp_arb;
+	unsigned long fifo_watermark1;
+	unsigned long fifo_watermark2;
+	unsigned long fifo_watermark3;
+	unsigned long fifo_watermark4;
+	unsigned long fifo_watermark5;
+	unsigned long fifo_watermark6;
+} mode_data_tnc_t;
+
+#define CHECK_VGA(a) MODE_IS_VGA(a)
+
+#ifdef DEBUG_BUILD_TYPE
+#define FLAG(a) a
+#else
+/* Turn all workaround for release driver */
+#define FLAG(a) 1
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pd/cmn/pd.c b/drivers/gpu/drm/emgd/emgd/display/pd/cmn/pd.c
new file mode 100755
index 0000000..0ac0e9c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pd/cmn/pd.c
@@ -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/drivers/gpu/drm/emgd/emgd/display/pi/cmn/displayid.c b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/displayid.c
new file mode 100644
index 0000000..186ce7d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/displayid.c
@@ -0,0 +1,1109 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: displayid.c
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains functions to parse DisplayID into a data strucuture.
+ *  Supported DisplayID versions:
+ *  VESA DisplayID Standard Verion 1 12/13/2007
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.dpd
+
+#include <io.h>
+#include <memory.h>
+
+#include <igd_errno.h>
+
+#include <displayid.h>
+#include <pi.h>
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+#ifndef CONFIG_NO_DISPLAYID
+
+/* IMP NOTE:
+ *     Keep the order of datablocks as it is.
+ *     DisplayID parser directly access the offset using tag as an index.
+ */
+unsigned short db_offset[] = {
+#ifdef CONFIG_MICRO
+	OS_OFFSETOF(displayid_t, dummy_db),        /* PRODUCTID        0x00 */
+	OS_OFFSETOF(displayid_t, display_params),  /* DISPLAY_PARAMS   0x01 */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* COLOR_CHARS      0x02 */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* TIMING_1_DETAIL  0x03 */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* TIMING_2_DETAIL  0x04 */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* TIMING_3_SHORT   0x05 */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* TIMING_4_DMTID   0x06 */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* VESA_TIMING_STD  0x07 */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* CEA_TIMING_STD   0x08 */
+	OS_OFFSETOF(displayid_t, timing_range),    /* VIDEO_RANGE      0x09 */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* SERIAL_NUMBER    0x0A */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* ASCII_STRING     0x0B */
+	OS_OFFSETOF(displayid_t, display_dev),     /* DISPLAY_DEVICE   0x0C */
+	OS_OFFSETOF(displayid_t, lvds),            /* LVDS_INTERFACE   0x0D */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* TRANSFER_CHAR    0x0E */
+	OS_OFFSETOF(displayid_t, display_intf),    /* DISPLAY_INTF     0x0F */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* STEREO_INTF      0x10 */
+#else
+	OS_OFFSETOF(displayid_t, productid),       /* PRODUCTID        0x00 */
+	OS_OFFSETOF(displayid_t, display_params),  /* DISPLAY_PARAMS   0x01 */
+	OS_OFFSETOF(displayid_t, color_char),      /* COLOR_CHARS      0x02 */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* TIMING_1_DETAIL  0x03 */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* TIMING_2_DETAIL  0x04 */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* TIMING_3_SHORT   0x05 */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* TIMING_4_DMTID   0x06 */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* VESA_TIMING_STD  0x07 */
+	OS_OFFSETOF(displayid_t, dummy_db),        /* CEA_TIMING_STD   0x08 */
+	OS_OFFSETOF(displayid_t, timing_range),    /* VIDEO_RANGE      0x09 */
+	OS_OFFSETOF(displayid_t, serial_num),      /* SERIAL_NUMBER    0x0A */
+	OS_OFFSETOF(displayid_t, general_string),  /* ASCII_STRING     0x0B */
+	OS_OFFSETOF(displayid_t, display_dev),     /* DISPLAY_DEVICE   0x0C */
+	OS_OFFSETOF(displayid_t, lvds),            /* LVDS_INTERFACE   0x0D */
+	OS_OFFSETOF(displayid_t, transfer_char),   /* TRANSFER_CHAR    0x0E */
+	OS_OFFSETOF(displayid_t, display_intf),    /* DISPLAY_INTF     0x0F */
+	OS_OFFSETOF(displayid_t, stereo_intf),     /* STEREO_INTF      0x10 */
+#endif
+
+
+#if 0
+	/* Vendor specific tag is out of order, so it cannot be here. See
+	 * case DATABLOCK_VENDOR_SPECIFIC for implementation. */
+	OS_OFFSETOF(displayid_t, vendor),          /* VENDOR_SPECIFIC  0x7F */
+#endif
+};
+
+type_std_t vesa_std_lookup[] =
+{
+	/* width  height refresh flags */
+	/* byte 0 bit 0->7 */
+	{  640,    350,    85,   0                 },   /* bit 0 */
+	{  640,    400,    85,   0                 },   /* bit 1 */
+	{  720,    400,    85,   0                 },   /* bit 2 */
+	{  640,    480,    60,   0                 },   /* bit 3 */
+	{  640,    480,    72,   0                 },   /* bit 4 */
+	{  640,    480,    75,   0                 },   /* bit 5 */
+	{  640,    480,    85,   0                 },   /* bit 6 */
+	{  800,    600,    56,   0                 },   /* bit 7 */
+
+	/* byte 1 bit 0->7 */
+	{  800,    600,    60,   0                 },   /* bit 0 */
+	{  800,    600,    72,   0                 },   /* bit 1 */
+	{  800,    600,    75,   0                 },   /* bit 2 */
+	{  800,    600,    85,   0                 },   /* bit 3 */
+	{  800,    600,   120,   PD_MODE_RB        },   /* bit 4 */
+	{  848,    480,    60,   0                 },   /* bit 5 */
+	{ 1024,    768,    43,   PD_SCAN_INTERLACE },   /* bit 6 */
+	{ 1024,    768,    60,   0                 },   /* bit 7 */
+
+	/* byte 2 bit 0->7 */
+	{ 1024,    768,    70,   0                 },   /* bit 0 */
+	{ 1024,    768,    75,   0                 },   /* bit 1 */
+	{ 1024,    768,    85,   0                 },   /* bit 2 */
+	{ 1024,    768,   120,   PD_MODE_RB        },   /* bit 3 */
+	{ 1152,    864,    75,   0                 },   /* bit 4 */
+	{ 1280,    768,    60,   PD_MODE_RB        },   /* bit 5 */
+	{ 1280,    768,    60,   0                 },   /* bit 6 */
+	{ 1280,    768,    75,   0                 },   /* bit 7 */
+
+	/* byte 3 bit 0->7 */
+	{ 1280,    768,    85,   0                 },   /* bit 0 */
+	{ 1280,    768,   120,   PD_MODE_RB        },   /* bit 1 */
+	{ 1280,    800,    60,   PD_MODE_RB        },   /* bit 2 */
+	{ 1280,    800,    60,   0                 },   /* bit 3 */
+	{ 1280,    800,    75,   0                 },   /* bit 4 */
+	{ 1280,    800,    85,   0                 },   /* bit 5 */
+	{ 1280,    800,   120,   PD_MODE_RB        },   /* bit 6 */
+	{ 1280,    960,    60,   0                 },   /* bit 7 */
+
+	/* byte 4 bit 0->7 */
+	{ 1280,    960,    85,   0                 },   /* bit 0 */
+	{ 1280,    960,   120,   PD_MODE_RB        },   /* bit 1 */
+	{ 1280,   1024,    60,   0                 },   /* bit 2 */
+	{ 1280,   1024,    75,   0                 },   /* bit 3 */
+	{ 1280,   1024,    85,   0                 },   /* bit 4 */
+	{ 1280,   1024,   120,   PD_MODE_RB        },   /* bit 5 */
+	{ 1360,    768,    60,   0                 },   /* bit 6 */
+	{ 1360,    768,   120,   PD_MODE_RB        },   /* bit 7 */
+
+	/* byte 5 bit 0->7 */
+	{ 1400,   1050,    60,   PD_MODE_RB        },   /* bit 0 */
+	{ 1400,   1050,    60,   0                 },   /* bit 1 */
+	{ 1400,   1050,    75,   0                 },   /* bit 2 */
+	{ 1400,   1050,    85,   0                 },   /* bit 3 */
+	{ 1400,   1050,   120,   PD_MODE_RB        },   /* bit 4 */
+	{ 1440,    900,    60,   PD_MODE_RB        },   /* bit 5 */
+	{ 1440,    900,    60,   0                 },   /* bit 6 */
+	{ 1440,    900,    75,   0                 },   /* bit 7 */
+
+	/* byte 6 bit 0->7 */
+	{ 1440,    900,    85,   0                 },   /* bit 0 */
+	{ 1440,    900,   120,   PD_MODE_RB        },   /* bit 1 */
+	{ 1600,   1200,    60,   0                 },   /* bit 2 */
+	{ 1600,   1200,    65,   0                 },   /* bit 3 */
+	{ 1600,   1200,    70,   0                 },   /* bit 4 */
+	{ 1600,   1200,    75,   0                 },   /* bit 5 */
+	{ 1600,   1200,    85,   0                 },   /* bit 6 */
+	{ 1600,   1200,   120,   PD_MODE_RB        },   /* bit 7 */
+
+	/* byte 7 bit 0->7 */
+	{ 1680,   1050,    60,   PD_MODE_RB        },   /* bit 0 */
+	{ 1680,   1050,    60,   0                 },   /* bit 1 */
+	{ 1680,   1050,    75,   0                 },   /* bit 2 */
+	{ 1680,   1050,    85,   0                 },   /* bit 3 */
+	{ 1680,   1050,   120,   PD_MODE_RB        },   /* bit 4 */
+	{ 1792,   1344,    60,   0                 },   /* bit 5 */
+	{ 1792,   1344,    75,   0                 },   /* bit 6 */
+	{ 1792,   1344,   120,   PD_MODE_RB        },   /* bit 7 */
+
+	/* byte 8 bit 0->7 */
+	{ 1856,   1392,    60,   0                 },   /* bit 0 */
+	{ 1856,   1392,    75,   0                 },   /* bit 1 */
+	{ 1856,   1392,   120,   PD_MODE_RB        },   /* bit 2 */
+	{ 1920,   1200,    60,   PD_MODE_RB        },   /* bit 3 */
+	{ 1920,   1200,    60,   0                 },   /* bit 4 */
+	{ 1920,   1200,    75,   0                 },   /* bit 5 */
+	{ 1920,   1200,    85,   0                 },   /* bit 6 */
+	{ 1920,   1200,   120,   PD_MODE_RB        },   /* bit 7 */
+
+	/* byte 9 bit 0->7 */
+	{ 1920,   1440,    60,   0                 },   /* bit 0 */
+	{ 1920,   1440,    75,   0                 },   /* bit 1 */
+	{ 1920,   1440,   120,   PD_MODE_RB        },   /* bit 2 */
+	{ 2560,   1600,    60,   PD_MODE_RB        },   /* bit 3 */
+	{ 2560,   1600,    60,   0                 },   /* bit 4 */
+	{ 2560,   1600,    75,   0                 },   /* bit 5 */
+	{ 2560,   1600,    85,   0                 },   /* bit 6 */
+	{ 2560,   1600,   120,   PD_MODE_RB        },   /* bit 7 */
+};
+
+#ifndef CONFIG_MICRO
+/*!
+ * Function to replace common timings in 1st list with 2nd list, 2nd list
+ * is unchanged.
+ *
+ * @param dtds1
+ * @param dtds2
+ *
+ * @return void
+ */
+void replace_vesa_dtds_with_cea_dtds(igd_timing_info_t *dtds1,
+	igd_timing_info_t *dtds2)
+{
+	igd_timing_info_t *temp;
+
+	if (!dtds2 || !dtds1) {
+		return;
+	}
+
+	while (dtds1->width != IGD_TIMING_TABLE_END) {
+		temp = dtds2;
+
+		while (temp->width != IGD_TIMING_TABLE_END) {
+			if ((temp->width   == dtds1->width) &&
+				(temp->height  == dtds1->height) &&
+				(temp->refresh == dtds1->refresh)) {
+				dtds1->mode_info_flags &= ~PD_MODE_SUPPORTED;
+			}
+			temp++;
+		}
+		dtds1++;
+	}
+}
+#endif
+
+#ifdef DEBUG_FIRMWARE
+/*!
+ *
+ * @param db
+ *
+ * @return void
+ */
+void displayid_print_datablock(datablock_t *db)
+{
+	unsigned char payload_string[800];
+	unsigned char i, j;
+
+	/* Get the payload data into a string */
+	OS_MEMSET(payload_string, 0, sizeof(payload_string));
+	for (i=0, j=0; i<db->payload; i++,j+=5) {
+		payload_string[j] = '0';
+		payload_string[j+1] = 'x';
+		if ((db->payload_data[i]>>4) <= 0x9) {
+			payload_string[j+2] = '0' + (db->payload_data[i]>>4);
+		} else {
+			payload_string[j+2] = 'A' + (db->payload_data[i]>>4) - 0xA;
+		}
+		if ((db->payload_data[i] & 0x0F) <= 0x9) {
+			payload_string[j+3] = '0' + (db->payload_data[i]&0x0F);
+		} else {
+			payload_string[j+3] = 'A' + (db->payload_data[i]&0x0F) - 0xA;
+		}
+		payload_string[j+4] = ' ';
+	}
+	payload_string[j] = '\0';
+
+	EMGD_DEBUG("Tag = %u", db->tag);
+	EMGD_DEBUG("Version = %u", db->revision);
+	EMGD_DEBUG("Payload = %u", db->payload);
+	EMGD_DEBUG("Payload data = %s", payload_string);
+}
+
+/*!
+ *
+ * @param buffer
+ * @param did
+ *
+ * @return void
+ */
+void displayid_print(unsigned char *buffer, displayid_t *did)
+{
+	unsigned short i;
+	display_params_t *dp = &did->display_params;
+	timing_range_t   *tr = &did->timing_range;
+	lvds_display_t   *ld = &did->lvds;
+	display_dev_t    *dd = &did->display_dev;
+	display_intf_t   *di = &did->display_intf;
+#ifndef CONFIG_MICRO
+	productid_t      *pi = &did->productid;
+	color_char_t     *cc = &did->color_char;
+	serial_number_t  *sn = &did->serial_num;
+	general_string_t *gs = &did->general_string;
+	transfer_char_t  *tc = &did->transfer_char;
+	stereo_intf_t    *si = &did->stereo_intf;
+	vendor_t         *vi = &did->vendor;
+#endif
+
+	DISPLAYID_PRINT_LINE();
+	EMGD_DEBUG("DisplayID Version: %d", did->version);
+	EMGD_DEBUG("DisplayID Revision: %d", did->revision);
+	DISPLAYID_PRINT_LINE();
+	EMGD_DEBUG("Size of different structures:");
+	DISPLAYID_PRINT_LINE();
+	EMGD_DEBUG("     displayid_t = %d", sizeof(displayid_t));
+	EMGD_DEBUG("display_params_t = %d", sizeof(display_params_t));
+	EMGD_DEBUG("     type1_dtd_t = %d", sizeof(type1_dtd_t));
+	EMGD_DEBUG("     type2_dtd_t = %d", sizeof(type2_dtd_t));
+	EMGD_DEBUG("     type3_cvt_t = %d", sizeof(type3_cvt_t));
+	EMGD_DEBUG("      type_std_t = %d", sizeof(type_std_t));
+	EMGD_DEBUG("  timing_range_t = %d", sizeof(timing_range_t));
+	EMGD_DEBUG("   display_dev_t = %d", sizeof(display_dev_t));
+	EMGD_DEBUG("  lvds_display_t = %d", sizeof(lvds_display_t));
+	EMGD_DEBUG("  display_intf_t = %d", sizeof(display_intf_t));
+	EMGD_DEBUG("        dummy_db = %d", 256);
+	EMGD_DEBUG("         timings = %d",
+		sizeof(pd_timing_t)*DISPLAYID_MAX_NUM_TIMINGS);
+	EMGD_DEBUG("           attrs = %d",
+		sizeof(pd_attr_t)*DISPLAYID_MAX_ATTRS);
+
+#ifndef CONFIG_MICRO
+	EMGD_DEBUG("     productid_t = %d", sizeof(productid_t));
+	EMGD_DEBUG("    color_char_t = %d", sizeof(color_char_t));
+	EMGD_DEBUG(" serial_number_t = %d", sizeof(serial_number_t));
+	EMGD_DEBUG("general_string_t = %d", sizeof(general_string_t));
+	EMGD_DEBUG(" transfer_char_t = %d", sizeof(transfer_char_t));
+	EMGD_DEBUG("   stereo_intf_t = %d", sizeof(stereo_intf_t));
+	EMGD_DEBUG("        vendor_t = %d", sizeof(vendor_t));
+
+	DISPLAYID_PRINT_LINE();
+	EMGD_DEBUG("PRODUCT ID DATA BLOCK");
+	DISPLAYID_PRINT_LINE();
+	displayid_print_datablock((datablock_t *)pi);
+	EMGD_DEBUG("       vendor = %c%c%c",
+		pi->vendor[0], pi->vendor[1], pi->vendor[2]);
+	EMGD_DEBUG(" product_code = %u", pi->product_code);
+	EMGD_DEBUG("serial_number = %lu", pi->serial_number);
+	EMGD_DEBUG("    manf_week = %u", pi->manf_week);
+	EMGD_DEBUG("    manf_year = %u", pi->manf_year+2000);
+	EMGD_DEBUG("   string_len = %u", pi->string_size);
+	EMGD_DEBUG("       string = %s", pi->string);
+
+	DISPLAYID_PRINT_LINE();
+	EMGD_DEBUG("COLOR CHARACTERISTICS DATA BLOCK");
+	DISPLAYID_PRINT_LINE();
+	displayid_print_datablock((datablock_t *)cc);
+
+	DISPLAYID_PRINT_LINE();
+	EMGD_DEBUG("SERIAL NUMBER DATA BLOCK");
+	DISPLAYID_PRINT_LINE();
+	displayid_print_datablock((datablock_t *)sn);
+
+	DISPLAYID_PRINT_LINE();
+	EMGD_DEBUG("GENERAL PURPOSE ASCII STRING DATA BLOCK");
+	DISPLAYID_PRINT_LINE();
+	displayid_print_datablock((datablock_t *)gs);
+
+	DISPLAYID_PRINT_LINE();
+	EMGD_DEBUG("TRANSFER CHARACTERISTICS DATA BLOCK");
+	DISPLAYID_PRINT_LINE();
+	displayid_print_datablock((datablock_t *)tc);
+
+	DISPLAYID_PRINT_LINE();
+	EMGD_DEBUG("STEREO INTERFACE DATA BLOCK");
+	DISPLAYID_PRINT_LINE();
+	displayid_print_datablock((datablock_t *)si);
+
+	DISPLAYID_PRINT_LINE();
+	EMGD_DEBUG("VENDOR SPECIFIC DATA BLOCK");
+	DISPLAYID_PRINT_LINE();
+	displayid_print_datablock((datablock_t *)vi);
+#endif
+
+	DISPLAYID_PRINT_LINE();
+	EMGD_DEBUG("DISPLAY PARAMETERS DATA BLOCK");
+	DISPLAYID_PRINT_LINE();
+	displayid_print_datablock((datablock_t *)dp);
+	EMGD_DEBUG("horz_image_size = %u", dp->horz_image_size);
+	EMGD_DEBUG("vert_image_size = %u", dp->vert_image_size);
+	EMGD_DEBUG("    horz_pixels = %u", dp->horz_pixels);
+	EMGD_DEBUG("    vert_pixels = %u", dp->vert_pixels);
+	EMGD_DEBUG(" deinterlacable = %u", dp->deinterlacing);
+	EMGD_DEBUG("   fixed_timing = %u", dp->fixed_timing);
+	EMGD_DEBUG("      fixed_res = %u", dp->fixed_res);
+	EMGD_DEBUG("   aspect_ratio = %u", dp->aspect_ratio);
+	EMGD_DEBUG(" native_color_depth(bppc) = %u", dp->native_color_depth+1);
+	EMGD_DEBUG("overall_color_depth(bppc) = %u", dp->overall_color_depth+1);
+
+	DISPLAYID_PRINT_LINE();
+	EMGD_DEBUG("VIDEO TIMING RANGESS DATA BLOCK");
+	DISPLAYID_PRINT_LINE();
+	displayid_print_datablock((datablock_t *)tr);
+	EMGD_DEBUG("  min_dclk = %lu KHz", tr->min_dclk);
+	EMGD_DEBUG("  max_dclk = %lu KHz", tr->max_dclk);
+	EMGD_DEBUG(" min_hrate = %u KHz", tr->min_hrate);
+	EMGD_DEBUG(" max_hrate = %u KHz", tr->max_hrate);
+	EMGD_DEBUG("min_hblank = %u pixels", tr->min_hblank);
+	EMGD_DEBUG(" min_vrate = %u Hz", tr->min_vrate);
+	EMGD_DEBUG(" max_vrate = %u Hz", tr->max_vrate);
+	EMGD_DEBUG("min_vblank = %u lines", tr->min_vblank);
+
+	DISPLAYID_PRINT_LINE();
+	EMGD_DEBUG("LVDS DISPLAY DATA BLOCK");
+	DISPLAYID_PRINT_LINE();
+	displayid_print_datablock((datablock_t *)ld);
+	EMGD_DEBUG("min_T1 = %u ms", ld->min_t1/10);
+	EMGD_DEBUG("max_T1 = %u ms", ld->max_t1*2);
+	EMGD_DEBUG("max_T2 = %u ms", ld->max_t2*2);
+	EMGD_DEBUG("max_T3 = %u ms", ld->max_t3*2);
+	EMGD_DEBUG("min_T4 = %u ms", ld->min_t4*10);
+	EMGD_DEBUG("min_T5 = %u ms", ld->min_t5*10);
+	EMGD_DEBUG("min_T6 = %u ms", ld->min_t6*10);
+
+	DISPLAYID_PRINT_LINE();
+	EMGD_DEBUG("DISPLAY DEVICE DATA BLOCK");
+	DISPLAYID_PRINT_LINE();
+	displayid_print_datablock((datablock_t *)dd);
+	EMGD_DEBUG("   horz_pixel_count = %u", dd->horz_pixel_count);
+	EMGD_DEBUG("   vert_pixel_count = %u", dd->vert_pixel_count);
+	EMGD_DEBUG("display_color_depth = %u", dd->display_color_depth);
+
+	DISPLAYID_PRINT_LINE();
+	EMGD_DEBUG("DISPLAY INTERFACE DATA BLOCK");
+	DISPLAYID_PRINT_LINE();
+	displayid_print_datablock((datablock_t *)di);
+	EMGD_DEBUG("         num_channels = %u", di->num_channels);
+	EMGD_DEBUG("            intf_type = %u", di->intf_type);
+	EMGD_DEBUG("      RGB_color_depth = %u", di->rgb_color_depth);
+	EMGD_DEBUG("YCrCb_444_color_depth = %u", di->ycbcr_444_color_depth);
+	EMGD_DEBUG("YCrCb_422_color_depth = %u", di->ycbcr_422_color_depth);
+	if(di->intf_type == INTERFACE_LVDS) {
+		EMGD_DEBUG("         openldi = %u", di->lvds.openldi);
+	}
+
+	DISPLAYID_PRINT_LINE();
+	EMGD_DEBUG("Detailed Timing Descriptors");
+	DISPLAYID_PRINT_LINE();
+
+	for (i=0; i<did->num_timings; i++) {
+		EMGD_DEBUG("DTD: %u", i+1);
+		EMGD_DEBUG("          dclk = %lu", did->timings[i].dclk);
+		EMGD_DEBUG("       hactive = %u", did->timings[i].width);
+		EMGD_DEBUG("        htotal = %u", did->timings[i].htotal);
+		EMGD_DEBUG("  hblank_start = %u", did->timings[i].hblank_start);
+		EMGD_DEBUG("   hsync_start = %u", did->timings[i].hsync_start);
+		EMGD_DEBUG("     hsync_end = %u", did->timings[i].hsync_end);
+		EMGD_DEBUG("    hblank_end = %u", did->timings[i].hblank_end);
+		EMGD_DEBUG("       vactive = %u", did->timings[i].height);
+		EMGD_DEBUG("        vtotal = %u", did->timings[i].vtotal);
+		EMGD_DEBUG("  vblank_start = %u", did->timings[i].vblank_start);
+		EMGD_DEBUG("   vsync_start = %u", did->timings[i].vsync_start);
+		EMGD_DEBUG("     vsync_end = %u", did->timings[i].vsync_end);
+		EMGD_DEBUG("    vblank_end = %u", did->timings[i].vblank_end);
+		EMGD_DEBUG("        native = %u",
+			(did->timings[i].mode_info_flags&PD_MODE_DTD_FP_NATIVE)?1:0);
+		EMGD_DEBUG("     interlace = %u",
+			(did->timings[i].mode_info_flags&PD_SCAN_INTERLACE)?1:0);
+		EMGD_DEBUG("hsync_polarity = %s",
+			(did->timings[i].mode_info_flags & PD_HSYNC_HIGH)?
+			"ACTIVE HIGH":"ACTIVE LOW");
+		EMGD_DEBUG("vsync_polarity = %s",
+			(did->timings[i].mode_info_flags & PD_VSYNC_HIGH)?
+			"ACTIVE HIGH":"ACTIVE LOW");
+		DISPLAYID_PRINT_LINE();
+	}
+
+	/* Print the attributes */
+	if (did->num_attrs) {
+		EMGD_DEBUG("\tAttr\tID\tVALUE");
+		EMGD_DEBUG("----------------------");
+		for (i=0; i<did->num_attrs; i++) {
+			EMGD_DEBUG("\t%u\t%lu\t%lu", i+1, did->attr_list[i].id,
+				did->attr_list[i].current_value);
+		}
+		EMGD_DEBUG("----------------------");
+	}
+}
+#endif
+
+/*!
+ * Function to convert Type I - Detailed to pd_timing_t
+ *
+ * @param timing
+ * @param dtd
+ *
+ * @return void
+ */
+void convert_type1_to_pd(pd_timing_t *timing, type1_dtd_t *dtd)
+{
+	unsigned long refresh;
+	timing->dclk =                            /* change to KHz */
+		((unsigned long)dtd->dclk.lsb_dclk|
+		((unsigned long)dtd->dclk.msb_dclk<<16))*10;
+
+	/* DisplayID fields are 0 based but should be interpreted as 1-based.
+	 * For example hsync_width value can be read as 0-65,535 pixels but
+	 * interpreted as 1-65,536. So, to get the right value add 1.
+	 * But pd_timing_t values are 0 based except width and height,
+	 * so care should be taken while converting DisplayID fields into
+	 * pd_timing_t values */
+	timing->hblank_start = dtd->hactive;
+	timing->width = dtd->hactive + 1;
+	timing->hblank_end = timing->hblank_start + dtd->hblank + 1;
+	timing->hsync_start = timing->hblank_start + dtd->hsync_offset + 1;
+	timing->hsync_end = timing->hsync_start + dtd->hsync_width + 1;
+	timing->htotal = timing->hblank_end;
+
+	timing->vblank_start = dtd->vactive;
+	timing->height = dtd->vactive + 1;
+	timing->vblank_end = timing->vblank_start + dtd->vblank + 1;
+	timing->vsync_start = timing->vblank_start + dtd->vsync_offset + 1;
+	timing->vsync_end = timing->vsync_start + dtd->vsync_width + 1;
+	timing->vtotal = timing->vblank_end;
+
+	refresh = ((timing->dclk * 1000L)/timing->htotal)/timing->vtotal;
+	timing->refresh = (unsigned short) refresh;
+
+	timing->mode_info_flags = PD_MODE_DTD|PD_MODE_SUPPORTED;
+	if (dtd->hsync_polarity) {
+		timing->mode_info_flags |= PD_HSYNC_HIGH;
+	}
+	if (dtd->vsync_polarity) {
+		timing->mode_info_flags |= PD_VSYNC_HIGH;
+	}
+	if (dtd->interlaced) {
+		timing->mode_info_flags |= PD_SCAN_INTERLACE;
+	}
+	if (dtd->preferred) {
+		timing->mode_info_flags |= PD_MODE_DTD_FP_NATIVE;
+	}
+}
+
+/*!
+ * Function to convert Type II - Detailed to pd_timing_t
+ *
+ * @param timing
+ * @param dtd
+ *
+ * @return void
+ */
+void convert_type2_to_pd(pd_timing_t *timing, type2_dtd_t *dtd)
+{
+	unsigned long refresh;
+	timing->dclk =                            /* change to KHz */
+		((unsigned long)dtd->dclk.lsb_dclk|
+		((unsigned long)dtd->dclk.msb_dclk<<16))*10;
+
+	/* DisplayID fields are 0 based but should be interpreted as 1-based.
+	 * For example hsync_width value can be read as 0-15 OCTETs but
+	 * interpreted as 1-16 OCTETs. So, to get the right value add 1.
+	 * But pd_timing_t values are 0 based except width and height,
+	 * so care should be taken while converting DisplayID fields into
+	 * pd_timing_t values */
+	timing->width = (dtd->hactive + 1) * 8;    /* change to pixels */
+	timing->hblank_start = timing->width - 1;
+	timing->hblank_end = timing->hblank_start + (dtd->hblank + 1) * 8;
+	timing->hsync_start = timing->hblank_start + (dtd->hsync_offset + 1) * 8;
+	timing->hsync_end = timing->hsync_start + (dtd->hsync_width + 1) * 8;
+	timing->htotal = timing->hblank_end;
+
+	timing->vblank_start = dtd->vactive;
+	timing->height = dtd->vactive + 1;
+	timing->vblank_end = timing->vblank_start + dtd->vblank + 1;
+	timing->vsync_start = timing->vblank_start + dtd->vsync_offset + 1;
+	timing->vsync_end = timing->vsync_start + dtd->vsync_width + 1;
+	timing->vtotal = timing->vblank_end;
+
+	refresh = ((timing->dclk * 1000L)/timing->htotal)/timing->vtotal;
+	timing->refresh = (unsigned short) refresh;
+
+	timing->mode_info_flags = PD_MODE_DTD|PD_MODE_SUPPORTED;
+	if (dtd->interlaced) {
+		timing->mode_info_flags |= PD_SCAN_INTERLACE;
+	}
+	if (dtd->preferred) {
+		timing->mode_info_flags |= PD_MODE_DTD_FP_NATIVE;
+	}
+}
+
+/*!
+ * Function to filter timing table based on range block
+ *
+ * @param tt
+ * @param range
+ * @param firmware_type
+ *
+ * @return void
+ */
+void displayid_filter_range_timings(pd_timing_t *tt, timing_range_t *range,
+	unsigned char firmware_type)
+{
+	unsigned short hfreq;
+
+#define _HUNDRETHS(_n, _d)  ((100*_n)/_d)-((100*_n_d)/100),
+
+	#ifdef DEBUG_FIRMWARE
+	char result_str[60];
+	unsigned char pass_count = 0;
+	unsigned char fail_count = 0;
+
+	EMGD_DEBUG("Range limits:");
+	EMGD_DEBUG("\tmin_dclk = %lu KHz max_dclk = %lu KHz",
+		range->min_dclk, range->max_dclk);
+	EMGD_DEBUG("\t   h_min = %u h_max = %u KHz",
+		range->min_hrate, range->max_hrate);
+	EMGD_DEBUG("\t   v_min = %u v_max = %u",
+		range->min_vrate,range->max_vrate);
+	EMGD_DEBUG("WIDTH\tHEIGHT\tREFRESH\tH-FREQ\tDOTCLOCK\tRESULT");
+	EMGD_DEBUG("     \t      \t (Hz)  \t (KHz)\t (MHz)  \t      ");
+	EMGD_DEBUG("=====\t======\t=======\t======\t========\t======");
+#endif
+
+	/* If the display is a discreate frequency display, don't enable any
+	 * intermediate timings. Only continuous frequency displays requires
+	 * enabling range timings */
+	if (range->discrete_display) {
+		EMGD_DEBUG("Discrete display: Ranges aren't used.");
+		return;
+	}
+
+	/* If no timing table return */
+	if (tt == NULL) {
+		return;
+	}
+
+	/* Mark the timings that fall in the ranges */
+	/* Compare
+	 *     dclk in KHz
+	 *     hfreq in KHz
+	 *     vfreq in Hz */
+	while(tt->width != IGD_TIMING_TABLE_END) {
+		hfreq = (unsigned short)(tt->dclk/(unsigned long)tt->htotal); /* KHz */
+		if ((tt->dclk    >= (unsigned long)range->min_dclk)&&  /* compare KHz */
+			(tt->dclk    <= (unsigned long)range->max_dclk)&&  /* compare KHz */
+			(tt->refresh >= range->min_vrate) &&   /* compare Hz */
+			(tt->refresh <= range->max_vrate) &&   /* compare Hz */
+			(hfreq       >= range->min_hrate) &&   /* compare KHz */
+			(hfreq       <= range->max_hrate) &&   /* compare KHz */
+			(tt->hblank_end - tt->hblank_start) > range->min_hblank &&
+			(tt->vblank_end - tt->vblank_start) > range->min_vblank) {
+			tt->mode_info_flags |= PD_MODE_SUPPORTED;
+#ifdef DEBUG_FIRMWARE
+			if (tt->mode_info_flags & PD_MODE_SUPPORTED) {
+				EMGD_DEBUG("%5u\t%6u\t%7u\t%6u.%2u\t%8u.%2u\tPASSED",
+					tt->width, tt->height, tt->refresh,
+					tt->dclk/tt->htotal,
+					_HUNDRETHS(tt->dclk,tt->htotal),
+					tt->dclk/1000,
+					_HUNDRETHS(tt->dclk,1000);
+
+				pass_count++;
+			} else {
+			}
+#endif
+		} else {
+			/* Unmark the mode that falls out of range */
+			/* DTD, FACTORY and NATIVE timings are "GOLD" even if they
+			 * fall outside the range limits */
+			if (!(tt->mode_info_flags &
+				(PD_MODE_DTD|PD_MODE_FACTORY|PD_MODE_DTD_FP_NATIVE))) {
+#ifdef DEBUG_FIRMWARE
+				if ((tt->dclk <            /* compare KHz */
+						(unsigned long)range->min_dclk)||
+					(tt->dclk >
+						(unsigned long)range->max_dclk)) {
+					OS_MEMCPY(result_str, "FAILED DCLK    \0", 16);
+					fail_count++;
+				} else if ((tt->refresh > range->max_vrate) ||
+					(tt->refresh < range->min_vrate)) {
+					OS_MEMCPY(result_str, "FAILED REFRESH \0", 16);
+					fail_count++;
+				} else if ((hfreq < range->min_hrate) ||
+					(hfreq > range->max_hrate)) {
+					OS_MEMCPY(result_str, "FAILED H-FREQ  \0", 16);
+					fail_count++;
+				} else if ((tt->hblank_end-tt->hblank_start) <
+					range->min_hblank){
+					OS_MEMCPY(result_str, "FAILED MIN_HBLK\0", 16);
+				} else if ((tt->vblank_end-tt->vblank_start) <
+					range->min_vblank){
+					OS_MEMCPY(result_str, "FAILED MIN_VBLK\0", 16);
+				}
+				EMGD_DEBUG("%5u\t%6u\t%7u\t%6u.%2u\t%8u.%2u\t%s",
+					tt->width, tt->height, tt->refresh,
+					tt->dclk/tt->htotal,
+					_HUNDRETHS(tt->dclk,tt->htotal),
+					tt->dclk/1000,
+					_HUNDRETHS(tt->dclk,1000),
+					result_str);
+					((float) tt->dclk)/1000, result_str);
+
+				/* TODO: For multiple range blocks, don't disable the modes
+				 * that are outside the range. We already started with
+				 * an "empty supported table" */
+
+				/* But above assertion of "empty supported table" broke
+				 * if EDID ETF rules were met to enable all timings.
+				 * See edid.c for ETF conditions. So below line
+				 * cannot be commented out to support multiple range
+				 * blocks for DisplayID. */
+#endif
+				tt->mode_info_flags &= ~PD_MODE_SUPPORTED;
+			}
+		}
+		tt++;
+		if (tt->width == IGD_TIMING_TABLE_END && tt->extn_ptr) {
+			tt = tt->extn_ptr;
+		}
+	}
+#ifdef DEBUG_FIRMWARE
+	EMGD_DEBUG("pass count = %u, fail count = %u total = %u",
+		pass_count, fail_count, pass_count+fail_count);
+#endif
+} /* end displayid_filter_range_timings() */
+
+#define VESA_STD    1
+#define CEA_STD     2
+
+/*!
+ * Function to enable std timings: VESA STD or CEA STD
+ *
+ * @param tt1
+ * @param db_data
+ * @param lookup
+ * @param num_lookup
+ * @param std_type
+ *
+ * @return void
+ */
+void displayid_enable_std_timings(pd_timing_t *tt1, unsigned char *db_data,
+	type_std_t *lookup, unsigned short num_lookup, unsigned char std_type)
+{
+	unsigned short i;
+	pd_timing_t    *tt;
+	/* If no timing table return. This can happen if no edid_avail set not to
+	 * use std timings */
+	if (!tt1) {
+		return;
+	}
+
+	/* For every factory supported mode, enable it in the timing table */
+	for (i = 0; i < num_lookup; i++) {
+		tt = tt1;
+		/* i>>3 is nothing but dividing by 8, that gives the byte number,
+		 * i&0x7 is nothing but getting the bit position in that byte */
+		if (db_data[i>>3] & 1<<(i&0x7)) {
+			while(tt->width != IGD_TIMING_TABLE_END) {
+				if (lookup[i].width == tt->width &&
+					lookup[i].height == tt->height &&
+#if 0
+					(!((lookup[i].flags & (PD_SCAN_INTERLACE|PD_MODE_RB)) ^
+					(tt->mode_info_flags & (PD_SCAN_INTERLACE|PD_MODE_RB)))) &&
+#endif
+					(!((lookup[i].flags & PD_SCAN_INTERLACE) ^
+					(tt->mode_info_flags & PD_SCAN_INTERLACE))) &&
+					(!((lookup[i].flags & PD_ASPECT_16_9) ^
+					(tt->mode_info_flags & PD_ASPECT_16_9))) &&
+					lookup[i].refresh == tt->refresh) {
+					tt->mode_info_flags |= (PD_MODE_FACTORY|PD_MODE_SUPPORTED);
+					break;
+				}
+				tt++;
+				if (tt->width == IGD_TIMING_TABLE_END && tt->extn_ptr) {
+					tt = tt->extn_ptr;
+				}
+			}
+		}
+	}
+}
+
+static void displayid_parse_orientation_info (unsigned char orientation_blob,
+	igd_DID_rotation_info_t * rotation_info) {
+
+	unsigned int def_orientation = DEFAULT_ORIENTATION(orientation_blob);
+	unsigned int zero_pixel = ZERO_PIXEL(orientation_blob);
+	unsigned int scan_dir = SCAN_DIRECTION(orientation_blob);
+
+	/* Start with no rotation */
+	rotation_info->rotation = 0;
+	rotation_info->flip = 0;
+
+
+	if (def_orientation >= DEF_ORIENTATION_UNKNOWN) {
+		/* Display ID blob is corrupted or unknown configuration set */
+		EMGD_DEBUG("DisplayID: Unknown default orientation value: %d",
+			def_orientation);
+		return;
+	}
+
+	if (scan_dir == SCAN_DIRECTION_LONG) {
+		if (def_orientation == DEF_ORIENTATION_PORTRAIT) {
+			rotation_info->flip =
+				(zero_pixel == ZP_UPPER_LEFT || zero_pixel == ZP_LOWER_RIGHT);
+			rotation_info->rotation += 90;
+		} else { /* Landscape */
+			rotation_info->flip =
+				(zero_pixel == ZP_UPPER_RIGHT || zero_pixel == ZP_LOWER_LEFT);
+		}
+
+	} else if (scan_dir == SCAN_DIRECTION_SHORT) {
+		if (def_orientation == DEF_ORIENTATION_PORTRAIT) {
+			rotation_info->flip =
+				(zero_pixel == ZP_UPPER_RIGHT || zero_pixel == ZP_LOWER_LEFT);
+		}
+		else { /* Landscape */
+			rotation_info->flip =
+				(zero_pixel == ZP_UPPER_LEFT || zero_pixel == ZP_LOWER_RIGHT);
+			rotation_info->rotation += 90;
+		}
+	} else { /* Unknown scan direction */
+		EMGD_DEBUG("DisplayID: Unknown scan direction value: %d", scan_dir);
+		return;
+	}
+
+	/* zero pixel is in the lower-half: need to rotate by 180 degs */
+	if (zero_pixel == ZP_LOWER_LEFT || zero_pixel == ZP_LOWER_RIGHT)
+		rotation_info->rotation += 180;
+}
+
+/*!
+ * Function to parse DisplayID
+ *
+ * @param buffer
+ * @param did
+ * @param timing_table
+ * @param count
+ * @param upscale
+ *
+ * @return void
+ */
+int displayid_parse(
+		unsigned char *buffer,
+		displayid_t   *did,
+		pd_timing_t   *timing_table,
+		int           count,
+		unsigned char upscale)
+{
+	//unsigned char e = 0;
+	unsigned char checksum = 0, bytes_left;
+	unsigned short i;
+	unsigned short did_size;
+#ifndef CONFIG_MICRO
+	pd_timing_t   *cea_tmg_table;
+#endif
+	/* Read 4 bytes: (DisplayID Header)
+	 *       version, revision
+	 *       payload
+	 *       display product type identifier
+	 *       number of extensions */
+	*(unsigned long *) did = *(unsigned long *)buffer;
+
+	/* Check for version and revision */
+	if (did->version != 1 && did->revision != 0) {
+		EMGD_DEBUG("DisplayID Version %d.%d Unknown. Will Ignore.",
+			did->version, did->revision);
+		return DISPLAYID_NOT_SUPPORTED;
+	}
+
+	if (did->payload > 251) {
+		EMGD_DEBUG("DispID: Error: payload = %u not in [0..251]", did->payload);
+		return DISPLAYID_ERROR_PARSE;
+	}
+
+	/* Check sum check */
+	/* +5 is for 5 mandatory bytes */
+	did_size = (unsigned short) (did->payload + 5);
+	EMGD_DEBUG("DisplayID size = %u", did_size);
+	for (i = 0; i < did_size; i++) {
+		checksum += buffer[i];
+	}
+
+	/* bytes_left starts without DisplayID header */
+	bytes_left = did->payload;
+	/* current pointer is at 4 not at 5, because checksum byte is at the end */
+	buffer += 4;
+
+	if (checksum) {
+		EMGD_DEBUG("DisplayID checksum is incorrect! Will ignore.");
+		return DISPLAYID_ERROR_PARSE;
+	}
+
+	/* DisplayID parsing should start by disabling all modes.
+	 * Based on DisplayID data blocks modes will be enabled. */
+	enable_disable_timings(timing_table, 0);
+
+	/* Repeat for all extensions */
+	//e = did->num_extensions;
+	//while (e) {
+	{
+		//if (e != did->num_extensions) {
+			/* TODO: If there aren't enough bytes left in the buffer,
+			 * call I2C read function to read next DisplayID section */
+
+			/* Skip next section header 4 bytes */
+			//bytes_left -= 4;
+			//break;
+		//}
+
+		/* Parse Data Blocks */
+		/* Check minimum number of bytes required for Data Block were left */
+		while ((bytes_left > 3) && (bytes_left >= (buffer[2]+3))) {
+			unsigned char *db_data;
+			unsigned char payload = buffer[2] + 3;
+
+			/* displayid->datablock = buffer (for payload bytes) */
+			if (buffer[0] < sizeof(db_offset)/sizeof(unsigned short)) {
+				OS_MEMCPY(((unsigned char*)did) + db_offset[buffer[0]],
+					buffer, payload);
+			}
+
+			/* db_data points to payload data after db header (3 bytes),
+			 * Note: dummy_db offset is used for some DATA BLOCKS. See
+			 *       db_offset table above. */
+			db_data = (unsigned char *) &did->dummy_db[3];
+
+			switch (buffer[0]) {
+			/* Supported in Driver and VBIOS */
+			case DATABLOCK_DISPLAY_PARAMS:
+				/* Use following fields for fp_info:
+				 *     embedded use:      fixed timing
+				 *     horizontal pixels: fp_width
+				 *     vertical pixels:   fp_height */
+				did->attr_list[did->num_attrs].id = PD_ATTR_ID_PANEL_DEPTH;
+				did->attr_list[did->num_attrs].flags=PD_ATTR_FLAG_VALUE_CHANGED;
+				did->attr_list[did->num_attrs++].current_value =
+					(did->display_params.overall_color_depth+1)*3;
+				break;
+
+			case DATABLOCK_TIMING_1_DETAIL:
+				/* One Type I block can have multiple DTDs */
+				while (payload>=20&&did->num_timings<DISPLAYID_MAX_NUM_TIMINGS){
+					convert_type1_to_pd(&did->timings[did->num_timings++],
+						(type1_dtd_t *)db_data);
+					db_data += 20;
+					payload -= 20;
+					bytes_left -= 20;
+					buffer += 20;
+				}
+				/* Mark the end of the list */
+				did->timings[did->num_timings].width = IGD_TIMING_TABLE_END;
+				break;
+
+			case DATABLOCK_TIMING_2_DETAIL:
+				/* One Type II block can have multiple DTDs */
+				while (payload>=11&&did->num_timings<DISPLAYID_MAX_NUM_TIMINGS){
+					convert_type2_to_pd(&did->timings[did->num_timings++],
+						(type2_dtd_t *)db_data);
+					db_data += 11;
+					payload -= 11;
+					bytes_left -= 11;
+					buffer += 11;
+				}
+				did->timings[did->num_timings].width = IGD_TIMING_TABLE_END;
+				break;
+
+			case DATABLOCK_VESA_TIMING_STD:
+				/* VESA Standard Timings */
+				displayid_enable_std_timings(
+					timing_table,
+					db_data,
+					vesa_std_lookup,
+					sizeof(vesa_std_lookup)/sizeof(type_std_t),
+					VESA_STD);
+				break;
+
+			case DATABLOCK_VIDEO_RANGE:
+				/* convert from Hz/10,000 -> KHz by multiplying by 10 */
+				did->timing_range.min_dclk =
+					((unsigned long)did->timing_range.mindclk.lsb_min_dclk|
+					((unsigned long)did->timing_range.mindclk.msb_min_dclk
+						<<16))*10;
+
+				did->timing_range.max_dclk =
+					((unsigned long)did->timing_range.maxdclk.lsb_max_dclk|
+					((unsigned long)did->timing_range.maxdclk.msb_max_dclk
+						<<16))*10;
+				displayid_filter_range_timings(timing_table,&did->timing_range,
+					PI_FIRMWARE_DISPLAYID);
+				break;
+
+			case DATABLOCK_DISPLAY_DEVICE:
+				/* Get panel color depth */
+				did->attr_list[did->num_attrs].id = PD_ATTR_ID_PANEL_DEPTH;
+				did->attr_list[did->num_attrs].flags=PD_ATTR_FLAG_VALUE_CHANGED;
+				did->attr_list[did->num_attrs++].current_value =
+					(did->display_dev.display_color_depth+1)*3;
+				displayid_parse_orientation_info(did->display_dev.orientation,
+												&(did->rotation_info));
+				break;
+
+			case DATABLOCK_LVDS_INTERFACE:
+				/* Get T1-T5 values */
+				did->attr_list[did->num_attrs].id = PD_ATTR_ID_FP_PWR_T1;
+				did->attr_list[did->num_attrs].flags=PD_ATTR_FLAG_VALUE_CHANGED;
+				did->attr_list[did->num_attrs++].current_value =
+					did->lvds.max_t1*2 + did->lvds.max_t2*2;
+
+				did->attr_list[did->num_attrs].id = PD_ATTR_ID_FP_PWR_T2;
+				did->attr_list[did->num_attrs].flags=PD_ATTR_FLAG_VALUE_CHANGED;
+				did->attr_list[did->num_attrs++].current_value =
+					did->lvds.min_t5*10;
+
+				did->attr_list[did->num_attrs].id = PD_ATTR_ID_FP_PWR_T3;
+				did->attr_list[did->num_attrs].flags=PD_ATTR_FLAG_VALUE_CHANGED;
+				did->attr_list[did->num_attrs++].current_value =
+					did->lvds.min_t6*10;
+
+				did->attr_list[did->num_attrs].id = PD_ATTR_ID_FP_PWR_T4;
+				did->attr_list[did->num_attrs].flags=PD_ATTR_FLAG_VALUE_CHANGED;
+				did->attr_list[did->num_attrs++].current_value =
+					did->lvds.max_t3*2;
+
+				did->attr_list[did->num_attrs].id = PD_ATTR_ID_FP_PWR_T5;
+				did->attr_list[did->num_attrs].flags=PD_ATTR_FLAG_VALUE_CHANGED;
+				did->attr_list[did->num_attrs++].current_value =
+					did->lvds.min_t4*10 + did->lvds.max_t1*2;
+				break;
+
+			case DATABLOCK_DISPLAY_INTF:
+				if (did->display_intf.intf_type == INTERFACE_LVDS) {
+					/* Get number of channels: 0=singlechannel 1=dualchannel */
+					did->attr_list[did->num_attrs].id =
+						PD_ATTR_ID_2_CHANNEL_PANEL;
+					did->attr_list[did->num_attrs].flags =
+						PD_ATTR_FLAG_VALUE_CHANGED;
+					if (did->display_intf.num_channels == 2) {
+						did->attr_list[did->num_attrs++].current_value = 1;
+					}
+
+					/* Get panel type value: 0=normal 1=OpenLDI */
+					did->attr_list[did->num_attrs].id =
+						PD_ATTR_ID_LVDS_PANEL_TYPE;
+					did->attr_list[did->num_attrs].flags =
+						PD_ATTR_FLAG_VALUE_CHANGED;
+					did->attr_list[did->num_attrs++].current_value =
+						did->display_intf.lvds.openldi;
+				}
+
+				break;
+
+#ifndef CONFIG_MICRO
+			/* Support in Driver only */
+			case DATABLOCK_PRODUCTID:
+				break;
+
+			case DATABLOCK_SERIAL_NUMBER:
+				break;
+
+			case DATABLOCK_ASCII_STRING:
+				break;
+
+			case DATABLOCK_VENDOR_SPECIFIC:
+				/* Because vendor specific datablock tag is out-of-order,
+				 * copy data from buffer to vendor structure */
+				OS_MEMCPY(&did->vendor, buffer, buffer[2] + 3);
+				break;
+
+			/* Future support in Driver and VBIOS */
+			case DATABLOCK_TIMING_3_SHORT:
+				break;
+
+			case DATABLOCK_TIMING_4_DMTID:
+				break;
+
+			/* Future support in Driver */
+			case DATABLOCK_COLOR_CHARS:
+				break;
+
+			case DATABLOCK_CEA_TIMING_STD:
+				cea_tmg_table = (igd_timing_info_t *)
+					OS_ALLOC(cea_timing_table_size);
+				OS_MEMCPY(cea_tmg_table, cea_timing_table,
+					cea_timing_table_size);
+				/* Disable the CEA timings */
+				enable_disable_timings(cea_tmg_table, 0);
+				displayid_enable_std_timings(
+					cea_tmg_table,
+					db_data,
+					cea_std_lookup,
+					(unsigned short)cea_std_lookup_size,
+					CEA_STD);
+
+				replace_vesa_dtds_with_cea_dtds(timing_table, cea_tmg_table);
+				cea_tmg_table[cea_timing_table_size-1].extn_ptr =
+					(void *)timing_table;
+				timing_table = cea_tmg_table;
+				break;
+#endif
+			case DATABLOCK_TRANSFER_CHAR:
+				break;
+			}
+
+			/* Subtract data block payload */
+			bytes_left -= payload;
+			buffer += payload;
+		}
+		/* Extension count */
+		//e--;
+	}
+
+	return 0;
+}
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/cmn/edid.c b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/edid.c
new file mode 100644
index 0000000..d8a3c36
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/edid.c
@@ -0,0 +1,1187 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: edid.c
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file is contains all necessary functions for EDID reading and
+ *  parsing into a data strucutures.
+ *  Supported EDID versions:
+ *  EDID 1.3 (backward compatible with 1.1, 1.2)
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.dpd
+
+#include <io.h>
+
+#include <igd_errno.h>
+
+#include <memory.h>
+#include <displayid.h>
+#include <edid.h>
+#include <pi.h>
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/* Function to read EDID */
+/* Local functions */
+static void edid_mark_standard_timings(
+	unsigned char *buffer,
+	pd_timing_t   *timings,
+	int           established);
+
+static void edid_mark_detailed_timings(
+	unsigned char *buffer,
+	edid_t        *edid,
+	pd_timing_t   *timings,
+	unsigned char upscale);
+
+static void edid_parse_monitor_name(
+	unsigned char *buffer,
+	char          *name);
+
+/* Edid Releated Constants */
+
+static const unsigned char name_blockid[] = {0x00, 0x00, 0x00, 0xfc};
+static const unsigned char range_blockid[] = {0x00, 0x00, 0x00, 0xfd};
+static const unsigned char st_blockid[] = {0x00, 0x00, 0x00, 0xfa};
+static const unsigned char timings_mask[] = {0xff, 0xff, 0xff, 0x00};
+extern igd_timing_info_t cea_timing_table[];
+/*
+ * Translation from the "Established" bit field position to a
+ * hactive, vactive, refresh that can be searched for in the
+ * timings list.
+ */
+static unsigned char established_table[] = {
+	/* 800x600 @ 60Hz */
+	0x20, 0x03, 0x58, 0x02, 0x3c, 0x00,
+	/* 800x600 @ 56Hz */
+	0x20, 0x03, 0x58, 0x02, 0x38, 0x00,
+	/* 640x480 @ 75Hz */
+	0x80, 0x02, 0xe0, 0x01, 0x4b, 0x00,
+	/* 640x480 @ 72Hz */
+	0x80, 0x02, 0xe0, 0x01, 0x48, 0x00,
+	/* 640x480 @ 67Hz */
+	0x80, 0x02, 0xe0, 0x01, 0x43, 0x00,
+	/* 640x480 @ 60Hz */
+	0x80, 0x02, 0xe0, 0x01, 0x3c, 0x00,
+	/* 720x400 @ 88Hz */
+	0xd0, 0x02, 0x90, 0x01, 0x58, 0x00,
+	/* 720x400 @ 70Hz */
+	0xd0, 0x02, 0x90, 0x01, 0x46, 0x00,
+
+	/* 1280x1024 @ 75Hz */
+	0x00, 0x05, 0x00, 0x04, 0x4b, 0x00,
+	/* 1024x768 @ 75Hz */
+	0x00, 0x04, 0x00, 0x03, 0x4b, 0x00,
+	/* 1024x768 @ 70Hz */
+	0x00, 0x04, 0x00, 0x03, 0x46, 0x00,
+	/* 1024x768 @ 60Hz */
+	0x00, 0x04, 0x00, 0x03, 0x3c, 0x00,
+	/* 1024x768 @ 43Hz (i) */
+	0x00, 0x04, 0x00, 0x03, 0x2b, 0x00,
+	/* 832x624 @ 75Hz */
+	0x40, 0x03, 0x70, 0x02, 0x4b, 0x00,
+	/* 800x600 @ 75Hz */
+	0x20, 0x03, 0x58, 0x02, 0x4b, 0x00,
+	/* 800x600 @ 72Hz */
+	0x20, 0x03, 0x58, 0x02, 0x48, 0x00,
+
+	/* 1152x870 @ 75Hz */
+	0x80, 0x04, 0x66, 0x03, 0x4b, 0x00
+};
+
+#ifdef DEBUG_FIRMWARE
+/*!
+ *
+ * @param timing
+ * @param edid
+ *
+ * @return void
+ */
+static void print_supported_timings(
+	pd_timing_t *timing, edid_t *edid)
+{
+	unsigned short i, count = 0;
+	if (timing != NULL) {
+		while (timing->width != IGD_TIMING_TABLE_END) {
+			if (timing->mode_info_flags & PD_MODE_SUPPORTED) {
+				EMGD_DEBUG("\t%4u\t%4u\t%4u", timing->width,
+					timing->height, timing->refresh);
+				count++;
+			}
+
+			timing++;
+			if (timing->width == IGD_TIMING_TABLE_END && timing->extn_ptr) {
+				timing = timing->extn_ptr;
+			}
+		}
+	}
+
+	if (edid && edid->num_timings) {
+		for (i=0; i<edid->num_timings; i++) {
+			if (edid->timings[i].mode_info_flags & PD_MODE_SUPPORTED) {
+				EMGD_DEBUG("\t%4u\t%4u\t%4u", edid->timings[i].width,
+					edid->timings[i].height, edid->timings[i].refresh);
+				count++;
+			}
+		}
+	}
+	EMGD_DEBUG("Total supported timings = %u", count);
+}
+
+/*!
+ * Dump the EDID to the kernel messages for debug
+ *
+ * @param buffer
+ * @param size
+ *
+ * @return void
+ */
+void firmware_dump(unsigned char *buffer, unsigned short size)
+{
+	unsigned short i;
+	EMGD_DEBUG("---------------------------------------------------------");
+	if (*(unsigned long *) &buffer[0] == 0xFFFFFF00 &&
+		*(unsigned long *) &buffer[4] == 0x00FFFFFF) {
+		size = 128;
+		EMGD_DEBUG("EDID DUMP (size = %u):", size);
+	} else {
+		/* For DisplayID payload is at byte 2 */
+		/* +5 is for 5 mandatory bytes */
+		size = buffer[1]+5;
+		EMGD_DEBUG("DisplayID DUMP (size = %u):", size);
+	}
+	EMGD_DEBUG("-------+-------------------------------------------------");
+	EMGD_DEBUG("Offset | Data.....");
+	EMGD_DEBUG("-------+-------------------------------------------------");
+
+	for (i=0; i<size; i+=8) {
+		EMGD_DEBUG("  0x%2.2x | 0x%2.2x, 0x%2.2x, 0x%2.2x, 0x%2.2x, 0x%2.2x, 0x%2.2x, 0x%2.2x, 0x%2.2x",
+			i, buffer[i], buffer[i+1], buffer[i+2], buffer[i+3],
+			buffer[i+4], buffer[i+5], buffer[i+6], buffer[i+7]);
+	}
+	if (i>size) {
+		EMGD_DEBUG("Note: Ignore last row last %u bytes.", i-size);
+	}
+	EMGD_DEBUG("-------+-------------------------------------------------");
+	EMGD_DEBUG(" ");
+} /* edid_dump() */
+
+/*!
+ * Print the EDID Structure
+ *
+ * @param buffer
+ * @param size
+ *
+ * @return void
+ */
+void edid_print(edid_t *edid)
+{
+	int i;
+
+	EMGD_DEBUG("EDID Version: %d", edid->version);
+	EMGD_DEBUG("EDID Revision: %d", edid->revision);
+	EMGD_DEBUG("Vendor %s", edid->vendor);
+	EMGD_DEBUG("Model: %s", edid->name);
+	EMGD_DEBUG("Product Code: %ld", edid->product_code);
+	EMGD_DEBUG("Serial Number: %lu", edid->serial_number);
+	EMGD_DEBUG("Manufactored week: %d", edid->manf_week);
+	EMGD_DEBUG("Manufactored year: %ld", edid->manf_year);
+	EMGD_DEBUG("DPMS Flags: 0x%u", edid->dpms);
+	EMGD_DEBUG("Max Pixel Clock: %lu KHz", edid->range.max_dclk);
+	EMGD_DEBUG("H Range: %u - %u KHz",
+		edid->range.min_hrate, edid->range.max_hrate);
+	EMGD_DEBUG("V Range: %u - %u Hz",
+		edid->range.min_vrate, edid->range.max_vrate);
+
+	for (i=0; i<edid->num_timings; i++) {
+		EMGD_DEBUG("Detailied Timing Descriptor(DTD) %u", i+1);
+		EMGD_DEBUG("          dclk = %lu", edid->timings[i].dclk);
+		EMGD_DEBUG("       hactive = %u", edid->timings[i].width);
+		EMGD_DEBUG("        htotal = %u", edid->timings[i].htotal);
+		EMGD_DEBUG("  hblank_start = %u", edid->timings[i].hblank_start);
+		EMGD_DEBUG("   hsync_start = %u", edid->timings[i].hsync_start);
+		EMGD_DEBUG("     hsync_end = %u", edid->timings[i].hsync_end);
+		EMGD_DEBUG("    hblank_end = %u", edid->timings[i].hblank_end);
+		EMGD_DEBUG("       vactive = %u", edid->timings[i].height);
+		EMGD_DEBUG("        vtotal = %u", edid->timings[i].vtotal);
+		EMGD_DEBUG("  vblank_start = %u", edid->timings[i].vblank_start);
+		EMGD_DEBUG("   vsync_start = %u", edid->timings[i].vsync_start);
+		EMGD_DEBUG("     vsync_end = %u", edid->timings[i].vsync_end);
+		EMGD_DEBUG("    vblank_end = %u", edid->timings[i].vblank_end);
+		EMGD_DEBUG("     interlace = %u",
+			(edid->timings[i].mode_info_flags&PD_SCAN_INTERLACE)?1:0);
+		EMGD_DEBUG("hsync_polarity = %s",
+			(edid->timings[i].mode_info_flags & PD_HSYNC_HIGH)?
+			"ACTIVE HIGH":"ACTIVE LOW");
+		EMGD_DEBUG("vsync_polarity = %s",
+			(edid->timings[i].mode_info_flags & PD_VSYNC_HIGH)?
+			"ACTIVE HIGH":"ACTIVE LOW");
+	}
+} /* edid_print() */
+#endif
+
+/*!
+ * Function to disable all timings before marking supportecd timings
+ *
+ * @param timing
+ * @param enable
+ *
+ * @return void
+ */
+void enable_disable_timings(pd_timing_t *timing, unsigned char enable)
+{
+	if (!timing) {
+		return;
+	}
+
+	while(timing->width != IGD_TIMING_TABLE_END) {
+		if (enable) {
+			timing->mode_info_flags |= PD_MODE_SUPPORTED;
+		} else {
+			timing->mode_info_flags &= ~PD_MODE_SUPPORTED;
+		}
+		timing++;
+		if (timing->width == IGD_TIMING_TABLE_END && timing->extn_ptr) {
+			timing = timing->extn_ptr;
+		}
+	}
+}
+
+/*!
+ * Function to enable timings based on port driver flags
+ *
+ * @param timing
+ * @param enable
+ *
+ * @return void
+ */
+void enable_scaled_timings(pd_timing_t *timing, pd_timing_t *dtd,
+	unsigned char upscale)
+{
+
+	if (!upscale || !dtd || !timing) {
+		return;
+	}
+
+	/* If port driver supports up scaling, enable all smaller modes. */
+	while(timing->width != IGD_TIMING_TABLE_END) {
+		if ((timing->width <= dtd->width) &&
+			(timing->height <= dtd->height) &&
+			(timing->refresh <= dtd->refresh)) {
+			timing->mode_info_flags |= IGD_MODE_SUPPORTED;
+		}
+		timing++;
+
+		/* If reached the first table END,
+		 * then check for the added modes */
+		if (timing->width == IGD_TIMING_TABLE_END &&
+			timing->extn_ptr) {
+			timing = timing->extn_ptr;
+		}
+	}
+}
+
+/*!
+ * Parse an Edid Structure from a provided 128 byte buffer of data.
+ * This function will return EDID_READ_AGAIN if the driver should
+ * read another 128 bytes and call this function again. This will
+ * happen with EDID structures with one or more extended 128 byte regions.
+ * count is 0 on the first call and incremented with each extra 128
+ * byte buffer.
+ *
+ * This parser skips information that is not important to the driver.
+ * There should be an interface to provide the whole EDID to userspace
+ * where more advanced parsing can happen. If you need something exotic
+ * out of the EDID consider having a user app do it instead of making
+ * This in-kernel EDID parser large.
+ *
+ * Timings found in the "Established" and "Standard" bitfields or
+ * extension blocks will be looked up in the provided timings list.
+ * If a match is found the timings will be marked with
+ * PD_MODE_SUPPORTED.
+ *
+ * If the EDID provides frequency ranges all timings within the range will
+ * be marked with PD_MODE_SUPPORTED in timing_table.
+ *
+ * If a driver uses a single timings list for multiple displays the driver
+ * will have to copy the flags mentioned above into a bit range specific
+ * to each display (in the driver specific bit range).
+ *
+ * @param buffer
+ * @param edid
+ * @param timing_table
+ * @param count
+ * @param upscale
+ *
+ * @return 0 on success
+ * @return EDID_ERROR_PARSE on failure
+ */
+int edid_parse(
+		unsigned char *buffer,
+		edid_t        *edid,
+		pd_timing_t   *timing_table,
+		int           count,
+		unsigned char upscale)
+{
+	int           chksum = 0, i, j;
+	unsigned long version, vendor, temp32;
+	pd_timing_t   *timing;
+
+	if (!edid || !buffer) {
+		return EDID_ERROR_PARSE;
+	}
+
+	/* No count means, edid_parse() called for first time */
+	if (!count) {
+		OS_MEMSET(edid, 0, sizeof(edid_t));
+	}
+
+	/* Check the checksum */
+	for (i=0; i<128; i++) {
+		chksum += buffer[i];
+	}
+
+	if ((chksum & 0xff) != 0) {
+		EMGD_DEBUG("EDID checksum is incorrect! Will ignore.");
+		return EDID_ERROR_PARSE;
+	}
+
+	/* FIXME: Verify this, I think extra EDID blocks have no header */
+	if (count) {
+		/*	goto BLOCKS; */
+		return EDID_ERROR_PARSE;
+	}
+
+	/* Header already checked. Skip 8 bytes */
+	buffer+=8;
+
+	/* Vendor Name */
+	vendor = (buffer[0]<<8) | buffer[1];
+	*(unsigned long *)edid->vendor = ((vendor>>10) + 0x40) +
+		((((vendor>>5) & 0x1f) + 0x40)<<8) +
+		((unsigned long)((vendor & 0x1f) + 0x40)<<16);
+	buffer+=2;
+
+	/* Product Code */
+	edid->product_code = (buffer[1]<<8) | buffer[0];
+	buffer+=2;
+
+	/* Serial Number 4 bytes (SKIP)*/
+	edid->serial_number = buffer[0] |
+				(buffer[1]<<8) |
+				((unsigned long)(buffer[2])<<16) |
+				((unsigned long)(buffer[3])<<24);
+	buffer += 4;
+
+	/* Manufactured Week 1 byte (SKIP) */
+	edid->manf_week = buffer[0];
+	buffer++;
+
+	/* Manufactured Year 1 byte (SKIP) */
+	edid->manf_year = 1990 + buffer[0];
+	buffer++;
+
+	/* EDID Version/Revision 0x12-0x13 */
+	version = (buffer[0]<<8) | buffer[1];
+	edid->version = buffer[0];
+	edid->revision = buffer[1];
+	buffer += 2;
+
+	switch(version) {
+	case 0x0:
+	case 0x0101:
+	case 0x0102:
+	case 0x0103:
+		/* Possibly do something based on this */
+		break;
+	default:
+		EMGD_DEBUG("EDID Version %d.%d Unknown. Will Ignore.",
+			edid->version, edid->revision);
+		return EDID_ERROR_PARSE;
+		break;
+	}
+
+	/* Basic Display Params (SKIP) */
+	buffer+=4;
+
+	/* DPMS and Features 1 byte  */
+	edid->dpms = (buffer[0]>>5);
+	edid->display_type = (buffer[0]>>3) & 0x3;
+	edid->standard_color = (buffer[0]>>2) & 0x1;
+	edid->preferred_timing = (buffer[0]>>1) & 0x1;
+	edid->gtf = (buffer[0] & 0x1);
+	buffer++;
+
+	/* Color 10 bytes (SKIP)*/
+	buffer+=10;
+
+	/* EDID parsing should start by disabling all modes.
+	 * Based on EDID data, modes will be enabled. */
+	enable_disable_timings(timing_table, 0);
+
+	/* Based on the established timings provided in the EDID, mark the
+	 * timings in the table as below (as per meeting with MikeD on 7/11/03):
+	 *
+	 * 1. If all VESA ETF and 640x480 modes are supported,
+	 *     then mark all modes in the table as supported + DTD modes
+	 * 2. If all VESA ETF 60Hz modes are supported,
+	 *     then mark all 60Hz modes in the table as supported + DTD modes
+	 * 3. Default:
+	 *     Enable only ETF modes in the table + DTD modes
+	 *
+	 * Established Timings 3 bytes (SKIP bits 6:0 of byte 3 which contains
+	 * manufactorer's proprietary timings), so there are 17 established
+	 * timings. */
+
+	/* Move byte2 bit7 to byte2 bit0. This is done to maintain
+	 * continuation along with other 16 established timings */
+	temp32 = buffer[0] | ((unsigned long)(buffer[1])<<8) |
+		((unsigned long)(buffer[2]>>7)<<16);
+
+	/* Here are the bit definitions:
+	 *  Byte 0
+	 *       bit 0 - 800 x 600 @ 60Hz    VESA
+	 *       bit 1 - 800 x 600 @ 56Hz    VESA
+	 *       bit 2 - 640 x 480 @ 75Hz    VESA
+	 *       bit 3 - 640 x 480 @ 72Hz    VESA
+	 *       bit 4 - 640 x 480 @ 67Hz    Apple, Mac II
+	 *       bit 5 - 640 x 480 @ 60Hz    IBM, VGA
+	 *       bit 6 - 720 x 400 @ 88Hz    IBM, XGA2
+	 *       bit 7 - 720 x 400 @ 70Hz    IBM, VGA
+	 *  Byte 1
+	 *       bit 0 - 1280 x 1024 @ 75Hz  VESA
+	 *       bit 1 - 1024 x  768 @ 75Hz  VESA
+	 *       bit 2 - 1024 x  768 @ 70Hz  VESA
+	 *       bit 3 - 1024 x  768 @ 60Hz  VESA
+	 *       bit 4 - 1024 x  768 @ 87Hz  IBM (Interlaced)
+	 *       bit 5 -  832 x  624 @ 75Hz  Apple, Mac II
+	 *       bit 6 -  800 x  600 @ 75Hz  VESA
+	 *       bit 7 -  800 x  600 @ 72Hz  VESA
+	 *  Byte 2
+	 *       bit 0 - 1152 x  870 @ 75Hz  Apple, Mac II
+	 *
+	 * Note:
+	 *  Byte2 bit 0 used to be at Byte 2 bit 7 but moved to bit 0 for sake of
+	 *  continuality.
+	 */
+	for (i=0; i<=16; i++) {
+		if (temp32 & (1L<<i)) {
+			edid_mark_standard_timings(&established_table[i*6],
+				timing_table, 1);
+		}
+	}
+
+#ifdef DEBUG_FIRMWARE
+	EMGD_DEBUG("Supported timings after FIRST established timings.");
+	print_supported_timings(timing_table, edid);
+#endif
+
+	if (timing_table != NULL) {
+		/* Mark the other timings in the table, as per above notes. */
+		timing = timing_table;
+		while (timing->width != IGD_TIMING_TABLE_END) {
+			if ((temp32 & 0xCF2F) == 0xCF2F) {            /* Case 1 */
+				timing->mode_info_flags |= PD_MODE_SUPPORTED;
+			} else if (((temp32 & 0xCF2F) == 0x821) &&    /* Case 2 */
+				(timing->refresh == 60)) {
+				timing->mode_info_flags |= PD_MODE_SUPPORTED;
+			}
+
+			timing++;
+			if (timing->width == IGD_TIMING_TABLE_END && timing->extn_ptr) {
+				timing = timing->extn_ptr;
+			}
+		}
+	}
+
+	buffer+=3;
+
+	/* Standard Timings 16 bytes, Look these up in the standard
+	 * timings table to find the match. Skip any that are not found
+	 * in the table.
+	 */
+	for (i=0; i<8; i++) {
+		/* First 8 standard timings */
+		edid_mark_standard_timings(buffer, timing_table, 0);
+		buffer+=2;
+	}
+
+#ifdef DEBUG_FIRMWARE
+	EMGD_DEBUG("Supported timings after SECOND established timings.");
+	print_supported_timings(timing_table, edid);
+#endif
+
+	/* BLOCKS: */
+	/* Blocks of Data */
+	for (i=0; i<4; i++) {
+		if (*(unsigned long *)buffer == *(unsigned long *)name_blockid) {
+			/* Monitor Name */
+			edid_parse_monitor_name(&buffer[5], edid->name);
+			buffer+=18;
+			continue;
+		}
+		if (*(unsigned long *)buffer == *(unsigned long *)range_blockid) {
+			/* Monitor Limits */
+			edid->range_set = 1;
+			edid->range.min_vrate = buffer[5];      /* Hz */
+			edid->range.max_vrate = buffer[6];      /* Hz */
+			edid->range.min_hrate = buffer[7];      /* KHz */
+			edid->range.max_hrate = buffer[8];      /* KHz */
+			edid->range.max_dclk  =
+				(unsigned long)buffer[9]*10000L; /* convert from MHz/10->KHz */
+			/* Following are always zero:
+			 * edid->range.min_dclk
+			 * edid->range->min_hblank
+			 * edid->range->min_vblank */
+
+			/* Call common function to filter timings based on range limits */
+			displayid_filter_range_timings(timing_table, &edid->range,
+				PI_FIRMWARE_EDID);
+
+			/* Fixme GTF */
+			buffer+=18;
+			continue;
+		}
+		if (*(unsigned long *)buffer == *(unsigned long *)st_blockid) {
+			/* Additional 6 Standard Timings */
+			buffer+=5;
+			for (j=0; j<12; j+=2) {
+				edid_mark_standard_timings(&buffer[j], timing_table, 0);
+			}
+			buffer+=13;
+			continue;
+		}
+		if (*(unsigned long *)buffer & *(unsigned long *)timings_mask) {
+			/* Detailed Timings */
+			if (edid->num_timings >= NUM_TIMINGS-1) {
+				continue;
+			}
+			edid_mark_detailed_timings(buffer, edid, timing_table, upscale);
+			buffer+=18;
+			continue;
+		}
+		/* Don't handle Block types that don't matter */
+		buffer+=18;
+	} /* end for loop */
+
+#ifdef DEBUG_FIRMWARE
+	EMGD_DEBUG("FINAL supported timings .");
+	print_supported_timings(timing_table, edid);
+#endif
+
+	/* Extensions */
+	if (*buffer) {
+		return EDID_READ_AGAIN;
+	}
+
+	return 0;
+} /* end edid_parse() */
+
+/*!
+ * Given the two byte Standard Timings Identifier, Mark the timing
+ * that matches in the timings array.
+ * If "established" is set, the two byte "EDID id" will be used,
+ * otherwise the buffer should contain the hactive, followed by
+ * the vactive followed by the refresh, all in 16 bit LSB format.
+ *
+ * @param buffer
+ * @param timings
+ * @param established
+ *
+ * @return void
+ */
+static void edid_mark_standard_timings(
+		unsigned char *buffer,
+		pd_timing_t   *timings,
+		int           established)
+{
+	int hactive, vactive=0, refresh, aspect;
+
+	if ((!established) && (buffer[0] == 0x01) && (buffer[1] == 0x01)) {
+		return;
+	}
+	if (established) {
+		hactive = buffer[0] | (buffer[1]<<8);
+		vactive = buffer[2] | (buffer[3]<<8);
+		refresh = buffer[4] | (buffer[5]<<8);
+	}
+	else {
+		hactive = (buffer[0] + 31)<<3;
+		refresh = (buffer[1] & 0x1f) + 60;
+		aspect = buffer[1]>>6;
+		switch(aspect) {
+		case 0x0:
+			vactive = (hactive*10)>>4;
+			break;
+		case 0x1:
+			vactive = (hactive*3)>>2;
+			break;
+		case 0x2:
+			vactive = (hactive<<2)/5;
+			break;
+		case 0x3:
+			vactive = (hactive*9)>>4;
+			break;
+		default:
+			EMGD_ERROR("Invalid aspect ratio in EDID.");
+			return;
+		}
+	}
+
+	if (timings != NULL) {
+		/* Look for mode in table */
+		while (timings->width != IGD_TIMING_TABLE_END) {
+			/* By default no mode is supported. */
+			if ((timings->refresh == refresh) &&
+				(timings->width == hactive) &&
+				(timings->height == vactive)) {
+				timings->mode_info_flags |= PD_MODE_SUPPORTED;
+				return;
+			}
+
+			timings++;
+
+			if (timings->width == IGD_TIMING_TABLE_END && timings->extn_ptr) {
+				timings = timings->extn_ptr;
+			}
+		}
+	}
+
+	return;
+} /* end edid_mark_standard_timings() */
+
+/*!
+ * Parse a detailed timing block from the buffer provided and set the
+ * data in the pd_timing_t structure provided.
+ *
+ * @param buffer
+ * @param edid
+ * @param timing_table
+ * @param upscale
+ *
+ * @return void
+ */
+static void edid_mark_detailed_timings(
+		unsigned char *buffer,
+		edid_t        *edid,
+		pd_timing_t   *timing_table,
+		unsigned char upscale)
+{
+	unsigned long temp;
+	pd_timing_t *timings = &(edid->timings[edid->num_timings]);
+
+	timings->dclk = ((unsigned long)(buffer[1]<<8) | buffer[0]) * 10;  /* KHz */
+	timings->width = ((buffer[4] & 0xf0)<<4) | buffer[2];
+	if (timings->width == 0) {
+		/* Bail out as DTD is invalid. This happens as we are estimating the
+		 * amount of availabel DTD since manufacturer does not follow CEA
+		 * format */
+		timings->width = IGD_TIMING_TABLE_END;
+		return;
+	}
+	timings->hblank_start = timings->width - 1;
+	timings->hblank_end = timings->width +
+		(((buffer[4]& 0xf)<<8) | buffer[3]) - 1;
+	timings->height = ((buffer[7] & 0xf0)<<4) | buffer[5];
+	timings->vblank_start = timings->height - 1;
+	timings->vblank_end = timings->height +
+		(((buffer[7]& 0xf)<<8)| buffer[6]) - 1;
+	timings->hsync_start = timings->hblank_start +
+		(((buffer[11] & 0xc0)<<2) | buffer[8]);
+	timings->hsync_end = timings->hsync_start +
+		(((buffer[11] & 0x30)<<4) | buffer[9]);
+	timings->vsync_start = timings->vblank_start +
+		(((buffer[11] & 0xc)<<2) | (buffer[10]>>4));
+	timings->vsync_end = timings->vsync_start +
+		(((buffer[11] & 0x3)<<4) | (buffer[10] & 0xf));
+	timings->htotal = timings->hblank_end;
+	timings->vtotal = timings->vblank_end;
+
+	/* SKIP BORDER */
+	timings->mode_info_flags |= (buffer[17] & 0x80)?PD_SCAN_INTERLACE:0;
+
+	/* Need to divide width by 2 and set PIXEL_DOUBLE flag in order to properly */
+	/* handle clock doubled modes like 1440(720)x480i and 1440(720)x576i */
+	if( (timings->mode_info_flags & PD_SCAN_INTERLACE) && (timings->width == 1440) &&
+	    ((timings->height == 480) || (timings->height == 576)) )
+	{
+		timings->width /= 2;
+		timings->mode_info_flags |= IGD_PIXEL_DOUBLE;
+	}else if((timings->mode_info_flags & PD_SCAN_INTERLACE)){
+		/* The height needs to be multiplied by 2 here so OS would prepare the
+		   correct frame buffer size. Pipe programming needs to be aware of this */
+		timings->height			*= 2;
+		timings->vtotal			*= 2;
+		timings->vblank_start	*= 2;
+		timings->vblank_end		*= 2;
+		timings->vsync_start	*= 2;
+		timings->vsync_end		*= 2;
+	}
+
+	/* Set sync polarities */
+	if((buffer[17] & 0x18)==0x18) { /* Bit 4 and 3 above = 11*/
+		/* if Bit 2 = 1, then vsync polarity = positive */
+		timings->mode_info_flags |= (buffer[17] & 0x04)? IGD_VSYNC_HIGH: 0;
+		/* if Bit 1 = 1, then hsync polarity = positive */
+		timings->mode_info_flags |= (buffer[17] & 0x02)? IGD_HSYNC_HIGH: 0;
+	}
+
+	if((buffer[17] & 0x18)==0x10) { /* Bit 4 and 3 above = 10*/
+		/* if Bit 1 = 1, then hsync polarity = positive */
+		timings->mode_info_flags |= (buffer[17] & 0x02)? IGD_HSYNC_HIGH: 0;
+	}
+
+	if (timings->dclk == 0) {
+		timings->dclk = 1;
+	}
+	if (timings->htotal == 0) {
+		timings->htotal = 1;
+	}
+	if (timings->vtotal == 0) {
+		timings->vtotal = 1;
+	}
+
+	temp = (unsigned long)timings->htotal * (unsigned long)timings->vtotal;
+	timings->refresh = (unsigned short)((timings->dclk * 1000)/temp);
+	timings->mode_info_flags |= (PD_MODE_SUPPORTED | PD_MODE_DTD);
+
+	/* Save in the detailed timings of EDID */
+	edid->num_timings++;
+	/* Mark the end of the list */
+	edid->timings[edid->num_timings].width = IGD_TIMING_TABLE_END;
+
+	/* Enable scale timings */
+	enable_scaled_timings(timing_table, timings, upscale);
+} /* end edid_mark_detailed_timings() */
+
+/*!
+ * Get the 13 (or less) character Monitor name from the buffer and
+ * pad with nulls.
+ *
+ * @param buffer
+ * @param name
+ *
+ * @return void
+ */
+static void edid_parse_monitor_name(unsigned char *buffer, char *name)
+{
+	int i;
+	for (i=0; i<13; i++) {
+		if (buffer[i] == 0x0a) {
+			name[i] = 0;
+			break;
+		}
+		name[i] = buffer[i];
+	}
+	while (i<14) {
+		name[i] = 0;
+		i++;
+	}
+} /* edid_parse_monitor_name() */
+
+#ifndef CONFIG_MICRO
+/*!
+ *
+ * @param edid
+ *
+ * @return 0
+ */
+int parse_audio_block(edid_t *edid)
+{
+	int i;
+	cea_audio_format_t *tmp_audio;
+
+	for(i=0; i<(edid->cea->total_short_audio_desc); i++){
+		tmp_audio = edid->cea->short_audio_desc + i;
+		if(tmp_audio->audio_format_code == CEA_AUDIO_LPCM){
+			if(tmp_audio->_48khz){
+				edid->cea->audio_cap[0].max_channels = tmp_audio->max_channels;
+				edid->cea->audio_cap[0]._20bit = tmp_audio->_20bit;
+				edid->cea->audio_cap[0]._24bit = tmp_audio->_24bit;
+			}
+			if(tmp_audio->_96khz){
+				edid->cea->audio_cap[1].max_channels = tmp_audio->max_channels;
+				edid->cea->audio_cap[1]._20bit = tmp_audio->_20bit;
+				edid->cea->audio_cap[1]._24bit = tmp_audio->_24bit;
+				if(tmp_audio->_88khz){
+					edid->cea->_44ms = 1;
+				}
+			}
+			if(tmp_audio->_192khz){
+				edid->cea->audio_cap[2].max_channels = tmp_audio->max_channels;
+				edid->cea->audio_cap[2]._20bit = tmp_audio->_20bit;
+				edid->cea->audio_cap[2]._24bit = tmp_audio->_24bit;
+				if(tmp_audio->_176khz){
+					edid->cea->_44ms = 1;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+/*!
+ *
+ * @param buffer
+ * @param list
+ * @param block_size
+ * @param total_bytes
+ *
+ * @return 0 no read will happen
+ * @return total_blocks
+ */
+int read_data_block_collection(unsigned char *buffer,
+							   char **list,
+							   unsigned int block_size,/* Block size in byte */
+							   unsigned int total_bytes)
+{
+	unsigned int total_blocks;
+	unsigned int i;
+
+	total_blocks = total_bytes/block_size;
+	if(total_bytes <= 0 ){
+		/* No read will happen */
+		return 0;
+	}
+
+	if(*list !=NULL){
+		OS_FREE(*list);
+	}
+
+	*list = OS_ALLOC((sizeof(char)*total_bytes));
+	for(i=0;i<total_blocks;i++){
+		OS_MEMCPY(*list+i, buffer, block_size);
+		buffer+=block_size;
+	}
+
+	return total_blocks;
+}
+
+/*!
+ *
+ * @param buffer
+ * @param edid
+ * @param timings
+ * @param count
+ * @param upscale
+ *
+ * @return 0 on success
+ * @return EDID_ERROR_PARSE on failure
+ */
+int edid_parse_cea (unsigned char *buffer,
+					edid_t        *edid,
+					pd_timing_t   *timings,
+					int           count,
+					unsigned char upscale)
+{
+	unsigned int offset,i = 4,timing_in_edid = 0, j;
+	unsigned int tag_code, chksum=0;
+	unsigned char *data_block_buffer;
+	pd_timing_t     *cea_timings = NULL;
+	pd_timing_t		*temp_timings;
+	unsigned short header;
+
+	if (!buffer) {
+		return EDID_ERROR_PARSE;
+	}
+	/* This holds the buffer */
+	offset = buffer[2];
+	/* Check the checksum */
+	for( i=0; i<128; i++) {
+		chksum += buffer[i];
+	}
+	if ((chksum & 0xff) != 0) {
+		EMGD_ERROR("EDID checksum is incorrect! Will ignore.");
+		return EDID_ERROR_PARSE;
+	}
+
+	header = buffer[0];
+
+	/* DI-Extension(header == 0x40) Unsupported for now */
+	if(header != 0x02){	/* CEA-Extension */
+		EMGD_ERROR("Unknown Extension");
+		return EDID_ERROR_PARSE;
+	}
+
+	if(edid->cea == NULL){
+		edid->cea = (cea_extension_t *) OS_ALLOC(sizeof(cea_extension_t));
+	}
+	if(edid->cea == NULL){
+		EMGD_ERROR("Run out of memory");
+		return 1;
+	}
+	OS_MEMSET(edid->cea, 0 , (sizeof(cea_extension_t)));
+	edid->cea->rev_number	= buffer [1];
+	edid->cea->caps			= buffer [3];
+
+	// no data block found or data block exceeds maximum buffer size
+	if(offset == 0 || offset > 124) {
+		EMGD_ERROR("No data block and no DTD ");
+		return 1;
+	}
+
+	/* General Format of CEA Data Block Collection
+	// -----------+--------------------+--------------------------------------+
+	//            |Byte#   |Bits5-7    |       Bits 0-4                       |
+	// -----------|--------------------+--------------------------------------+
+	//            |  1     | Video Tag |Length = total #of video			  |
+	//            |        |    Code   |bytes following this byte (L1)        |
+	//            |--------------------+--------------------------------------+
+	//  Video     |  2     | CEA Short Video Descriptor 1                     |
+	//  Data      |--------+--------------------------------------------------|
+	//  Block     |  3     | CEA Short Video Descriptor 2                     |
+	//            |--------+--------------------------------------------------|
+	//            | ...    | ...                                              |
+	//            |-----------------------------------------------------------+
+	//            | 1+L1   | CEA Short Video Descriptor L1                    |
+	// -----------+--------------------+--------------------------------------+
+	//            | 2+L1   | Audio Tag |Length = total #of audio bytes		  |
+	//            |        |    Code   |following this byte (L2)              |
+	//            |--------------------+--------------------------------------+
+	//  Audio     | 3+L1   |                                                  |
+	//  Data      |--------+                                                  |
+	//  Block     | 4+L1   | CEA Short Audio Descriptor 1                     |
+	//            |--------+                                                  |
+	//            | 5+L1   |                                                  |
+	//            |-----------------------------------------------------------+
+	//            | ...    |                                                  |
+	//            |        |                                                  |
+	//            |        |                                                  |
+	//            | ...    |                                                  |
+	//            |------------------------------------------------------------
+	//            |L1+L2   |                                                  |
+	//            |--------|                                                  |
+	//            |1+L1+L2 | CEA Short Audio Descriptor L2/3                  |
+	//            |--------|                                                  |
+	//            |2+L1+L2 |                                                  |
+	// -----------+-----------------------------------------------------------+
+	//            |3+L1+L2 |  Speaker  |Length = total #of SA bytes following |
+	//            |        | Tag Code  |this byte (L1)                        |
+	//  Speaker   |-----------------------------------------------------------+
+	//  Allocation|4+L1+L2 |                                                  |
+	//  Data      |--------|                                                  |
+	//  Block     |5+L1+L2 | Speaker Allocation Data Block Payload(3 bytes)   |
+	//            |--------|                                                  |
+	//            |6+L1+L2 |                                                  |
+	// -----------+-----------------------------------------------------------+
+	//            |7+L1+L2 | VSDB  Tag |Length = total #of VSDB bytes		  |
+	//            |        |    Code   |following this byte (L1)              |
+	//  Vendor    |-----------------------------------------------------------+
+	//  Specific  |8+L1+L2 |                                                  |
+	//  Data      |--------|                                                  |
+	//  Block     |9+L1+L2 | 24-bit IEEE Registration Identifier (LSB first)  |
+	//            |--------|                                                  |
+	//            |10+L1+L2|                                                  |
+	//            |-----------------------------------------------------------+
+	//            | ...    | Vendor Specific Data block Payload               |
+	// -----------+-----------------------------------------------------------+*/
+	data_block_buffer=&buffer[4];
+	/* Start reading data block collection */
+	i = 0;
+	while(i<offset){
+		unsigned int total_bytes;
+		tag_code = (unsigned int)*data_block_buffer & 0xE0;
+		total_bytes = (unsigned int)*data_block_buffer & 0x1F;
+		data_block_buffer++;
+		i++;
+		switch(tag_code){
+			case CEA_VIDEO_DATA_BLOCK:
+				/* Reading Short Video Descriptor block */
+				edid->cea->total_short_video_desc =read_data_block_collection
+				   (data_block_buffer,
+					(char **)&edid->cea->short_video_desc,
+					1,/* Block size in byte */
+					total_bytes);
+				break;
+			case CEA_AUDIO_DATA_BLOCK:
+				/* Reading Short Audio Descriptor block */
+				edid->cea->total_short_audio_desc = read_data_block_collection
+					(data_block_buffer,
+					(char **)&edid->cea->short_audio_desc,
+					3,/* Block size in byte */
+					total_bytes);
+				/* uncomment this codes if this info is requred in the future */
+				/*for(j=0; j<total_bytes; j+=3){
+					OS_MEMCPY
+						(&edid->cea->misc_data[j],
+						(edid->cea->short_audio_desc + (j/3)),
+						sizeof(cea_audio_format_t));
+				}
+				edid->cea->sadc = (unsigned char)
+					edid->cea->total_short_audio_desc; */
+				break;
+			case CEA_VENDOR_DATA_BLOCK:
+				/* Reading Vendor Specific Descriptor block */
+				edid->cea->vendor_block.vendor_block_size = (unsigned char)total_bytes;
+				OS_MEMCPY(edid->cea->vendor_block.vendor_ieee_id, data_block_buffer, 3);
+				read_data_block_collection
+					(data_block_buffer,
+					(char **)&edid->cea->vendor_data_block,
+					3,
+					total_bytes);
+				break;
+			case CEA_SPEAKER_DATA_BLOCK:
+				/* Reading Speaker Data Descriptor block */
+				for(j=0; j<3; j++){
+					edid->cea->speaker_alloc_block[j] = data_block_buffer[j];
+				}
+				break;
+			default:
+				/* Ignore unknown block? */
+				EMGD_ERROR("Unknown Tag Code! : CEA extended data block");
+				break;
+		}
+		data_block_buffer+=(total_bytes);
+		i+=(total_bytes);
+	};
+
+	/* DPG codes show that they are manufacturer who doesn't follow the spec
+	   Calculate the maximum possible DTD from whatever empty space left.
+	   The Maximum DTD is 6*/
+	 i=(unsigned int)(128-offset-1)/18;
+	 i = (i>6)?6:i;
+
+	buffer+=offset;
+	while(i>0){
+		if (edid->num_timings >= NUM_TIMINGS-1) {
+				break;
+		}
+		edid_mark_detailed_timings(buffer, edid, timings, upscale);
+		buffer+=18;
+		i--;
+	};
+
+	/* Parse audio block to know panel audio capability */
+	parse_audio_block(edid);
+
+	cea_timings = (igd_timing_info_t *) OS_ALLOC(cea_timing_table_size);
+	OS_MEMCPY(cea_timings, cea_timing_table, cea_timing_table_size);
+
+	for(i=0; i<(unsigned int)edid->cea->total_short_video_desc; i++){
+		EMGD_DEBUG("Video Code %d",(int)(edid->cea->short_video_desc + i)->code);
+		temp_timings = cea_timings;
+		timing_in_edid = 0;
+		while (temp_timings->width != IGD_TIMING_TABLE_END){
+			/* Look for matching tag code */
+			if((edid->cea->short_video_desc + i)->code == temp_timings->mode_number){
+				j=0;
+				while(j<edid->num_timings){
+					/* Ignore if we have already read the timng through DTD
+					   dclk would be sufficient to differentiate between progressive
+					   and interlace */
+					if(temp_timings->width == edid->timings[j].width &&
+					   temp_timings->height == edid->timings[j].height &&
+					   temp_timings->refresh == edid->timings[j].refresh &&
+					   temp_timings->dclk == edid->timings[j].dclk){
+						timing_in_edid = 1;
+						break;
+					}
+					j++;
+				}
+				/* Add the timing if we have not done so through DTD */
+				if(!(timing_in_edid)){
+					if (edid->num_timings >= NUM_TIMINGS-1) {
+							break;
+					}
+					OS_MEMCPY(&edid->timings[edid->num_timings],
+							  temp_timings, sizeof(pd_timing_t));
+					edid->timings[edid->num_timings].mode_number = 0;
+					edid->timings[edid->num_timings].mode_info_flags
+						|= (PD_MODE_SUPPORTED | PD_MODE_DTD);
+					edid->num_timings++;
+					edid->timings[edid->num_timings].width = IGD_TIMING_TABLE_END;
+					/*enable_scaled_timings(timings,
+						&edid->timings[edid->num_timings], upscale);*/
+				}
+				break;
+			}
+			temp_timings++;
+		}
+	}
+
+	OS_FREE(cea_timings);
+
+#ifdef DEBUG_FIRMWARE
+	EMGD_ERROR("FINAL supported timings after CEA .");
+	print_supported_timings(timings, edid);
+#endif
+	return 0;
+}
+#endif
+
+/*!
+ *
+ * @param buffer
+ * @param edid
+ * @param timings
+ * @param count
+ * @param upscale
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int edid_ext_parse(
+		unsigned char *buffer,
+		edid_t        *edid,
+		pd_timing_t   *timings,
+		int           count,
+		unsigned char upscale)
+{
+	unsigned int timing_in_edid = 0, j;
+#ifndef CONFIG_MICRO
+	if(edid_parse_cea(buffer, edid, timings, count, upscale)){
+		EMGD_ERROR("Reading cea extension ERROR!");
+		return 1;
+	}
+#endif
+
+	/* Check to see if 640x480 is part of EDID timing if not add it in.
+	   CEA panels does not support standard timing 640x480 */
+	for(j=0; j<edid->num_timings; j++){
+		if(edid->timings[j].width == 640 &&
+		   edid->timings[j].height == 480 &&
+		   edid->timings[j].refresh == 60 ){
+			timing_in_edid = 1;
+			break;
+		}
+	}
+	if((!timing_in_edid) && (edid->num_timings < NUM_TIMINGS-1)){
+		OS_MEMCPY(&edid->timings[edid->num_timings],
+							  cea_timing_table, sizeof(pd_timing_t));
+		edid->timings[edid->num_timings].mode_number = 0x101;
+		edid->timings[edid->num_timings].mode_info_flags
+			|= (PD_MODE_SUPPORTED | PD_MODE_DTD);
+		edid->num_timings++;
+		edid->timings[edid->num_timings].width = IGD_TIMING_TABLE_END;
+	}
+
+	return 0;
+}/* end edid_parse_ext() */
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/cmn/i2c_dispatch.h b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/i2c_dispatch.h
new file mode 100755
index 0000000..ae98630
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/i2c_dispatch.h
@@ -0,0 +1,78 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: i2c_dispatch.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _I2C_DISPATCH_H
+#define _I2C_DISPATCH_H
+
+/*
+ * IO.h is needed to resolve the FAR define
+ * context.h is needed for the igd_display_context_t
+ */
+
+#include <io.h>
+#include <context.h>
+#include <mode.h>
+
+#include <pd.h>
+
+#define I2C_DEFAULT_SPEED 100  /* Default I2C bus speed in KHz */
+#define DDC_DEFAULT_SPEED  10  /* Default DDC bus speed in KHz */
+
+/*
+ * Flags for Write Reg List
+ *
+ * Serial Write: Write a Reg Value, Data Value repeatedly within one
+ *  write cycle.
+ */
+#define IGD_I2C_SERIAL_WRITE 0x1
+#define IGD_I2C_WRITE_FW 0x2
+
+typedef struct _i2c_dispatch {
+	int (*i2c_read_regs)(
+		igd_context_t *context,
+		unsigned long i2c_bus,
+		unsigned long i2c_speed,
+		unsigned long dab,
+		unsigned char reg,
+		unsigned char FAR *buffer,
+		unsigned long num_bytes,
+		unsigned long flags);
+	int (*i2c_write_reg_list)(
+		igd_context_t *context,
+		unsigned long i2c_bus,
+		unsigned long i2c_speed,
+		unsigned long dab,
+		pd_reg_t *reg_list,
+		unsigned long flags);
+} i2c_dispatch_t;
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/cmn/igd_pi.c b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/igd_pi.c
new file mode 100644
index 0000000..1cf54ce
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/igd_pi.c
@@ -0,0 +1,260 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_pi.c
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Callback functions to give to port drivers. All functions are provided
+ *  to port driver as callback functions. Only port driver should call
+ *  these functions.
+ *-----------------------------------------------------------------------------
+ */
+
+#include <context.h>
+
+#include <memory.h>
+#include <sched.h>
+
+/* #include <igd_pi.h> */
+#include <igd_debug.h>
+
+#include <pi.h>
+#include <pd.h>
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/*!
+ * Function to register with main driver.
+ *
+ * @param handle
+ * @param pd_driver
+ *
+ * @return pi_pd_register()
+ */
+int igd_pd_register(void *handle, void *pd_driver)
+{
+	return pi_pd_register(pd_driver);
+} /* igd_pd_register */
+
+/*!
+ * Function to allocate memory
+ *
+ * @param handle
+ * @param pd_driver
+ *
+ * @return void
+ */
+void *igd_pd_malloc(unsigned long size)
+{
+	return OS_ALLOC(size);
+} /* end igd_pd_malloc */
+
+/*!
+ * Function to set the memory
+ *
+ * @param address
+ * @param c
+ * @param size
+ *
+ * @return void
+ */
+void *igd_pd_memset(void *address, int c, unsigned long size)
+{
+	return OS_MEMSET(address, c, size);
+} /* end igd_pd_memset */
+
+/*!
+ * Function to copy block of memory
+ *
+ * @param dst
+ * @param src
+ * @param size
+ *
+ * @return void
+ */
+void *igd_pd_memcpy(void *dst, void *src, unsigned long size)
+{
+	return OS_MEMCPY(dst, src, size);
+} /* end igd_pd_memcpy */
+
+/* Functions to free memory */
+void igd_pd_free(void *ptr)
+{
+	OS_FREE(ptr);
+} /* end igd_pd_free */
+
+/*!
+ * Function to sleep in micro seconds. This can be called with millisecond
+ * ranges.
+ *
+ * @param usec
+ *
+ * @return void
+ */
+void igd_pd_usleep(unsigned long usec)
+{
+	if (usec <= 1000) {
+		OS_SLEEP(usec);
+	} else {
+		os_alarm_t alarm = OS_SET_ALARM((usec+999)/1000);
+		do {
+			OS_SCHEDULE();
+		} while (!OS_TEST_ALARM(alarm));
+	}
+} /* end igd_pd_usleep() */
+
+/*!
+ * Function to do a string copy
+ *
+ * @param dest
+ * @param src
+ *
+ * @return dest
+ */
+char *igd_pd_strcpy(char *dest, char const *src)
+{
+	int i = 0;
+	/* This can be optimized by assigning 32 bit quantities instead
+	 * of 8 bit quantities. This requires knowing the length first then
+	 * move the quantities. For now, this is OK. */
+	while (src[i] != '\0') {
+		dest[i] = src[i];
+		i++;
+	}
+	dest[i] = '\0';
+	return (dest);
+} /* end igd_pd_strcpy() */
+
+/*!
+ * Function to check value of an attribute
+ *
+ * @param curr
+ * @param in
+ *
+ * @return PD_SUCCESS on success
+ * @return PD_ERR_NULL_PTR,PD_ERR_INVALID_ATTR, or PD_ERR_INCORR_ATTR_VALUE
+ * 	on failure
+ */
+int igd_pd_check_attr(pd_attr_t *curr, pd_attr_t *in)
+{
+	if (!curr || !in) {
+		return PD_ERR_NULL_PTR;
+	}
+
+	if (curr->id != in->id) {
+		return PD_ERR_INVALID_ATTR;
+	}
+
+	switch (curr->type) {
+		case PD_ATTR_TYPE_RANGE:
+			if ((in->current_value < RATTR(curr)->min) ||
+				(in->current_value > RATTR(curr)->max)) {
+				return PD_ERR_INCORR_ATTR_VALUE;
+			}
+			break;
+		case PD_ATTR_TYPE_LIST:
+			if ((in->current_value < 1) ||
+				(in->current_value > LHATTR(curr)->num_entries)) {
+				return PD_ERR_INCORR_ATTR_VALUE;
+			}
+			break;
+		case PD_ATTR_TYPE_BOOL:
+			if ((in->current_value != TRUE) &&
+				(in->current_value != FALSE)) {
+				return PD_ERR_INCORR_ATTR_VALUE;
+			}
+			break;
+		default:
+			return PD_ERR_INVALID_ATTR;
+	}
+	return PD_SUCCESS;
+} /* end igd_pd_check_attr() */
+
+/*!
+ * This function searches for the requested attr_id in the attribute list
+ * and returns the pointer.
+ *
+ * In case of LIST attribute, it will return the proper list entry.
+ *
+ * @param attr_list
+ * @param num_attrs
+ * @param attr_id
+ * @param flag
+ *
+ * @return attr_list on success
+ * @return NULL on failure
+ */
+pd_attr_t *igd_pd_get_attr(pd_attr_t *attr_list, unsigned long num_attrs,
+		unsigned long attr_id, unsigned long flag)
+{
+	unsigned long i;
+
+	if (!attr_list) {
+		return NULL;
+	}
+
+	for (i = 0; i < num_attrs; i++) {
+		if (attr_list[i].id == attr_id) {
+			if (attr_list[i].type == PD_ATTR_TYPE_LIST) {
+				if (flag == PD_GET_ATTR_LIST_ENTRY) {
+					return (&(attr_list[i+attr_list[i].current_value]));
+				} else {
+					return (&(attr_list[i]));
+				}
+			}
+			return (&(attr_list[i]));
+		}
+	}
+	return NULL;
+} /* end igd_pd_get_attr() */
+
+/*!
+ * Common mode filter algorithm for all port drivers
+ *
+ * @param context
+ * @param ilist
+ * @param olist
+ * @param dvo
+ * @param display
+ *
+ * @return pd_filter_timings()
+ */
+int igd_pd_filter_timings(
+	void *context,
+	pd_timing_t *ilist,
+	pd_timing_t **olist,
+	pd_dvo_info_t *dvo,
+	pd_display_info_t *display)
+{
+	return pd_filter_timings(context, ilist, olist, dvo, display);
+}
+
+igd_debug_t *igd_pd_get_igd_debug( void )
+{
+	return emgd_debug;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/cmn/mode_table.c b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/mode_table.c
new file mode 100644
index 0000000..d698875
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/mode_table.c
@@ -0,0 +1,2545 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mode_table.c
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains the mode resolution parameters.
+ *-----------------------------------------------------------------------------
+ */
+
+#define TRUE 1
+#define FALSE 0
+
+#include <config.h>
+#include <mode.h>
+
+/*
+ * If CONFIG_LIMIT_MODES is not defined then ALL modes should be included.
+ * Keep the defines here so that when adding new modes it is apparent that
+ * you should add it to the list below.
+ */
+#ifndef CONFIG_LIMIT_MODES
+#define CONFIG_MODE_640x480x60
+#define CONFIG_MODE_640x480x70
+#define CONFIG_MODE_640x480x72
+#define CONFIG_MODE_640x480x75
+#define CONFIG_MODE_640x480x85
+#define CONFIG_MODE_640x480x100
+#define CONFIG_MODE_640x480x120
+#define CONFIG_MODE_720x480x60
+#define CONFIG_MODE_720x576x50
+#define CONFIG_MODE_800x480x60
+#define CONFIG_MODE_800x600x60
+#define CONFIG_MODE_800x600x70
+#define CONFIG_MODE_800x600x72
+#define CONFIG_MODE_800x600x75
+#define CONFIG_MODE_800x600x85
+#define CONFIG_MODE_800x600x100
+#define CONFIG_MODE_800x600x120
+#define CONFIG_MODE_960x540x60
+#define CONFIG_MODE_1024x768x60
+#define CONFIG_MODE_1024x768x70
+#define CONFIG_MODE_1024x768x75
+#define CONFIG_MODE_1024x768x85
+#define CONFIG_MODE_1024x768x100
+#define CONFIG_MODE_1024x768x120
+#define CONFIG_MODE_1152x864x60
+#define CONFIG_MODE_1152x864x70
+#define CONFIG_MODE_1152x864x72
+#define CONFIG_MODE_1152x864x75
+#define CONFIG_MODE_1152x864x85
+#define CONFIG_MODE_1152x864x100
+#define CONFIG_MODE_1280x720x60
+#define CONFIG_MODE_1280x720x75
+#define CONFIG_MODE_1280x720x85
+#define CONFIG_MODE_1280x720x100
+#define CONFIG_MODE_1280x768x60
+#define CONFIG_MODE_1280x768x75
+#define CONFIG_MODE_1280x768x85
+#define CONFIG_MODE_1280x960x60
+#define CONFIG_MODE_1280x960x75
+#define CONFIG_MODE_1280x960x85
+#define CONFIG_MODE_1280x1024x60
+#define CONFIG_MODE_1280x1024x70
+#define CONFIG_MODE_1280x1024x72
+#define CONFIG_MODE_1280x1024x75
+#define CONFIG_MODE_1280x1024x85
+#define CONFIG_MODE_1280x1024x100
+#define CONFIG_MODE_1280x1024x120
+#define CONFIG_MODE_1366x768x60
+#define CONFIG_MODE_1400x1050x60
+#define CONFIG_MODE_1400x1050x75
+#define CONFIG_MODE_1400x1050x85
+#define CONFIG_MODE_1600x900x60
+#define CONFIG_MODE_1600x900x75
+#define CONFIG_MODE_1600x900x85
+#define CONFIG_MODE_1600x900x100
+#define CONFIG_MODE_1600x900x120
+#define CONFIG_MODE_1600x1200x60
+#define CONFIG_MODE_1600x1200x65
+#define CONFIG_MODE_1600x1200x70
+#define CONFIG_MODE_1600x1200x72
+#define CONFIG_MODE_1600x1200x75
+#define CONFIG_MODE_1600x1200x85
+#define CONFIG_MODE_1600x1200x100
+#define CONFIG_MODE_1600x1200x120
+#define CONFIG_MODE_1856x1392x60
+#define CONFIG_MODE_1856x1392x75
+#define CONFIG_MODE_1920x1080x50
+#define CONFIG_MODE_1920x1080x60
+#define CONFIG_MODE_1920x1080x75
+#define CONFIG_MODE_1920x1080x85
+#define CONFIG_MODE_1920x1080x100
+#define CONFIG_MODE_1920x1200x60
+#define CONFIG_MODE_1920x1200x75
+#define CONFIG_MODE_1920x1440x60
+#define CONFIG_MODE_1920x1440x75
+#define CONFIG_MODE_1920x1440x85
+#define CONFIG_MODE_2048x1536x60
+#define CONFIG_MODE_2048x1536x75
+/* CEA timings */
+#define CONFIG_CEA_MODE_640x480px60
+#ifndef CONFIG_MICRO
+/* These are timings that has duplicate except the difference in aspect
+   ratio. Since IEGD does not support diffrent aspect ratio removing
+   these CEA timings for now */
+/*
+#define CONFIG_CEA_MODE_720x480px60
+#define CONFIG_CEA_MODE_720x576px50*/
+#define CONFIG_CEA_MODE_720x480p_ax60
+#define CONFIG_CEA_MODE_720x576p_ax50
+#define CONFIG_CEA_MODE_1280x720p_ax50
+#define CONFIG_CEA_MODE_1280x720p_ax60
+#define CONFIG_CEA_MODE_1920x1080p_ax50
+#define CONFIG_CEA_MODE_1920x1080p_ax60
+#define CONFIG_CEA_MODE_1920x1080i_ax50
+#define CONFIG_CEA_MODE_1920x1080i_ax60
+#endif /* CONFIG_MICRO */
+
+#endif
+
+/*---------------------------------------------------------------------------
+ * Timing tables for CRT modes.
+ *---------------------------------------------------------------------------
+ */
+
+igd_timing_info_t crt_timing_table[] =
+{
+/* TODO: Add VESA standard REDUCED BLANKING (RB) timings to the table */
+#ifdef CONFIG_MODE_640x480x60
+	{
+		640, 480,              /* width, height */
+		60, 25175,             /* refresh, dot clock */
+		799,                   /* htotal */
+		647, 791,              /* hblank_start, hblank_end */
+		655, 751,              /* hsync_start, hsync_end */
+		524,                   /* vtotal */
+		487, 516,              /* vblank_start, vblank_end */
+		489, 491,              /* vsync_start, vsync_end */
+		0x101,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_640x480x70
+	{
+		640, 480,              /* width, height */
+		70, 28560,             /* refresh, dot clock */
+		815,                   /* htotal */
+		639, 815,              /* hblank_start, hblank_end */
+		663, 727,              /* hsync_start, hsync_end */
+		499,                   /* vtotal */
+		479, 499,              /* vblank_start, vblank_end */
+		480, 483,              /* vsync_start, vsync_end */
+		0x101,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_640x480x72
+	{
+		640, 480,              /* width, height */
+		72, 31500,             /* refresh, dot clock */
+		831,                   /* htotal */
+		647, 823,              /* hblank_start, hblank_end */
+		663, 703,              /* hsync_start, hsync_end */
+		519,                   /* vtotal */
+		487, 511,              /* vblank_start, vblank_end */
+		488, 491,              /* vsync_start, vsync_end */
+		0x101,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_640x480x75
+	{
+		640, 480,              /* width, height */
+		75, 31500,             /* refresh, dot clock */
+		839,                   /* htotal */
+		639, 839,              /* hblank_start, hblank_end */
+		655, 719,              /* hsync_start, hsync_end */
+		499,                   /* vtotal */
+		479, 499,              /* vblank_start, vblank_end */
+		480, 483,              /* vsync_start, vsync_end */
+		0x101,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_640x480x85
+	{
+		640, 480,              /* width, height */
+		85, 36000,             /* refresh, dot clock */
+		831,                   /* htotal */
+		639, 831,              /* hblank_start, hblank_end */
+		695, 751,              /* hsync_start, hsync_end */
+		508,                   /* vtotal */
+		479, 508,              /* vblank_start, vblank_end */
+		480, 483,              /* vsync_start, vsync_end */
+		0x101,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_640x480x100
+	{
+		640, 480,              /* width, height */
+		100, 43163,            /* refresh, dot clock */
+		847,                   /* htotal */
+		639, 847,              /* hblank_start, hblank_end */
+		679, 743,              /* hsync_start, hsync_end */
+		508,                   /* vtotal */
+		479, 508,              /* vblank_start, vblank_end */
+		480, 483,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_640x480x120
+	{
+		640, 480,              /* width, height */
+		120, 52406,            /* refresh, dot clock */
+		847,                   /* htotal */
+		639, 847,              /* hblank_start, hblank_end */
+		679, 743,              /* hsync_start, hsync_end */
+		514,                   /* vtotal */
+		479, 514,              /* vblank_start, vblank_end */
+		480, 483,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_720x400x70
+	/* NOTE: The above define is not auto-enabled. This is the VGA magic mode */
+	{   /* VGA Mode 2+,3+ */
+		720, 400,              /* width, height */
+		70, 28322,             /* refresh, dot clock */
+		899,                   /* htotal */
+		719, 899,              /* hblank_start, hblank_end */
+		773, 881,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		399, 448,              /* vblank_start, vblank_end */
+		412, 414,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_VSYNC_HIGH |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_720x480x60
+	{
+		720, 480,              /* width, height */
+		60, 27000,             /* refresh, dot clock */
+		857,                   /* htotal */
+		719, 857,              /* hblank_start, hblank_end */
+		735, 797,              /* hsync_start, hsync_end */
+		524,                   /* vtotal */
+		479, 524,              /* vblank_start, vblank_end */
+		488, 494,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_720x576x50
+	{
+		720, 576,              /* width, height */
+		50, 27500,             /* refresh, dot clock */
+		864,                   /* htotal */
+		719, 864,              /* hblank_start, hblank_end */
+		732, 795,              /* hsync_start, hsync_end */
+		625,                   /* vtotal */
+		575, 625,              /* vblank_start, vblank_end */
+		581, 587,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+	/* OFF BY Default, enable when PLB is merged */
+#ifdef CONFIG_MODE_800x480x60
+	{
+		800, 480,              /* width, height */
+		60, 33231,             /* refresh, dot clock */
+		1055,                  /* htotal */
+		799, 1055,             /* hblank_start, hblank_end */
+		863, 991,              /* hsync_start, hsync_end */
+		524,                   /* vtotal */
+		479, 524,              /* vblank_start, vblank_end */
+		500, 502,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_800x600x60
+	{
+		800, 600,              /* width, height */
+		60, 40000,             /* refresh, dot clock */
+		1055,                  /* htotal */
+		799, 1055,             /* hblank_start, hblank_end */
+		839, 967,              /* hsync_start, hsync_end */
+		627,                   /* vtotal */
+		599, 627,              /* vblank_start, vblank_end */
+		600, 604,              /* vsync_start, vsync_end */
+		0x103,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_800x600x70
+	{
+		800, 600,              /* width, height */
+		70, 45500,             /* refresh, dot clock */
+		1039,                  /* htotal */
+		799, 1039,             /* hblank_start, hblank_end */
+		839, 919,              /* hsync_start, hsync_end */
+		624,                   /* vtotal */
+		599, 624,              /* vblank_start, vblank_end */
+		600, 603,              /* vsync_start, vsync_end */
+		0x103,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_800x600x72
+	{
+		800, 600,              /* width, height */
+		72, 50000,             /* refresh, dot clock */
+		1039,                  /* htotal */
+		799, 1039,             /* hblank_start, hblank_end */
+		855, 975,              /* hsync_start, hsync_end */
+		665,                   /* vtotal */
+		599, 665,              /* vblank_start, vblank_end */
+		636, 642,              /* vsync_start, vsync_end */
+		0x103,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_800x600x75
+	{
+		800, 600,              /* width, height */
+		75, 49500,             /* refresh, dot clock */
+		1055,                  /* htotal */
+		799, 1055,             /* hblank_start, hblank_end */
+		815, 895,              /* hsync_start, hsync_end */
+		624,                   /* vtotal */
+		599, 624,              /* vblank_start, vblank_end */
+		600, 603,              /* vsync_start, vsync_end */
+		0x103,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_800x600x85
+	{
+		800, 600,              /* width, height */
+		85, 56250,             /* refresh, dot clock */
+		1047,                  /* htotal */
+		799, 1047,             /* hblank_start, hblank_end */
+		831, 895,              /* hsync_start, hsync_end */
+		630,                   /* vtotal */
+		599, 630,              /* vblank_start, vblank_end */
+		600, 603,              /* vsync_start, vsync_end */
+		0x103,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_800x600x100
+	{
+		800, 600,              /* width, height */
+		100, 68179,            /* refresh, dot clock */
+		1071,                  /* htotal */
+		799, 1071,             /* hblank_start, hblank_end */
+		847, 935,              /* hsync_start, hsync_end */
+		635,                   /* vtotal */
+		599, 635,              /* vblank_start, vblank_end */
+		600, 603,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_800x600x120
+	{
+		800, 600,              /* width, height */
+		120, 83950,            /* refresh, dot clock */
+		1087,                  /* htotal */
+		799, 1087,             /* hblank_start, hblank_end */
+		855, 943,              /* hsync_start, hsync_end */
+		642,                   /* vtotal */
+		599, 642,              /* vblank_start, vblank_end */
+		600, 603,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_960x540x60
+	{
+		960, 540,              /* width, height */
+		60, 40785,             /* refresh, dot clock */
+		1215,                  /* htotal */
+		959, 1215,             /* hblank_start, hblank_end */
+		991, 1087,             /* hsync_start, hsync_end */
+		558,                   /* vtotal */
+		539, 558,              /* vblank_start, vblank_end */
+		540, 543,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1024x768x60
+	{
+		1024, 768,             /* width, height */
+		60, 65000,             /* refresh, dot clock */
+		1343,                  /* htotal */
+		1023, 1343,            /* hblank_start, hblank_end */
+		1047, 1183,            /* hsync_start, hsync_end */
+		805,                   /* vtotal */
+		767, 805,              /* vblank_start, vblank_end */
+		770, 776,              /* vsync_start, vsync_end */
+		0x105,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1024x768x70
+	{
+		1024, 768,             /* width, height */
+		70, 75000,             /* refresh, dot clock */
+		1327,                  /* htotal */
+		1023, 1327,            /* hblank_start, hblank_end */
+		1047, 1183,            /* hsync_start, hsync_end */
+		805,                   /* vtotal */
+		767, 805,              /* vblank_start, vblank_end */
+		770, 776,              /* vsync_start, vsync_end */
+		0x105,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1024x768x75
+	{
+		1024, 768,             /* width, height */
+		75, 78750,             /* refresh, dot clock */
+		1311,                  /* htotal */
+		1023, 1311,            /* hblank_start, hblank_end */
+		1039, 1135,            /* hsync_start, hsync_end */
+		799,                   /* vtotal */
+		767, 799,              /* vblank_start, vblank_end */
+		768, 771,              /* vsync_start, vsync_end */
+		0x105,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1024x768x85
+	{
+		1024, 768,             /* width, height */
+		85, 94500,             /* refresh, dot clock */
+		1375,                  /* htotal */
+		1023, 1375,            /* hblank_start, hblank_end */
+		1071, 1167,            /* hsync_start, hsync_end */
+		807,                   /* vtotal */
+		767, 807,              /* vblank_start, vblank_end */
+		768, 771,              /* vsync_start, vsync_end */
+		0x105,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1024x768x100
+	{
+		1024, 768,             /* width, height */
+		100, 113310,           /* refresh, dot clock */
+		1391,                  /* htotal */
+		1023, 1391,            /* hblank_start, hblank_end */
+		1095, 1207,            /* hsync_start, hsync_end */
+		813,                   /* vtotal */
+		767, 813,              /* vblank_start, vblank_end */
+		768, 771,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1024x768x120
+	{
+		1024, 768,             /* width, height */
+		120, 139050,           /* refresh, dot clock */
+		1407,                  /* htotal */
+		1023, 1407,            /* hblank_start, hblank_end */
+		1103, 1215,            /* hsync_start, hsync_end */
+		822,                   /* vtotal */
+		767, 822,              /* vblank_start, vblank_end */
+		768, 771,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity H+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1152x864x60
+	{
+		1152, 864,             /* width, height */
+		60, 81624,             /* refresh, dot clock */
+		1519,                  /* htotal */
+		1151, 1519,            /* hblank_start, hblank_end */
+		1215, 1335,            /* hsync_start, hsync_end */
+		894,                   /* vtotal */
+		863, 894,              /* vblank_start, vblank_end */
+		864, 867,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1152x864x70
+	{
+		1152, 864,             /* width, height */
+		70, 97000,             /* refresh, dot clock */
+		1535,                  /* htotal */
+		1151, 1535,            /* hblank_start, hblank_end */
+		1223, 1343,            /* hsync_start, hsync_end */
+		899,                   /* vtotal */
+		863, 899,              /* vblank_start, vblank_end */
+		864, 867,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1152x864x72
+	{
+		1152, 864,             /* width, height */
+		72, 100000,            /* refresh, dot clock */
+		1535,                  /* htotal */
+		1151, 1535,            /* hblank_start, hblank_end */
+		1223, 1343,            /* hsync_start, hsync_end */
+		900,                   /* vtotal */
+		863, 900,              /* vblank_start, vblank_end */
+		864, 867,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1152x864x75
+	{
+		1152, 864,             /* width, height */
+		75, 108000,            /* refresh, dot clock */
+		1599,                  /* htotal */
+		1151, 1599,            /* hblank_start, hblank_end */
+		1215, 1343,            /* hsync_start, hsync_end */
+		899,                   /* vtotal */
+		863, 899,              /* vblank_start, vblank_end */
+		864, 867,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1152x864x85
+	{
+		1152, 864,             /* width, height */
+		85, 120000,            /* refresh, dot clock */
+		1551,                  /* htotal */
+		1151, 1551,            /* hblank_start, hblank_end */
+		1223, 1351,            /* hsync_start, hsync_end */
+		906,                   /* vtotal */
+		863, 906,              /* vblank_start, vblank_end */
+		864, 867,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1152x864x100
+	{
+		1152, 864,             /* width, height */
+		100, 144000,           /* refresh, dot clock */
+		1567,                  /* htotal */
+		1151, 1567,            /* hblank_start, hblank_end */
+		1231, 1359,            /* hsync_start, hsync_end */
+		914,                   /* vtotal */
+		863, 914,              /* vblank_start, vblank_end */
+		864, 867,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x720x60
+	{
+		1280, 720,             /* width, height */
+		60, 74481,             /* refresh, dot clock */
+		1663,                  /* htotal */
+		1279, 1663,            /* hblank_start, hblank_end */
+		1335, 1471,            /* hsync_start, hsync_end */
+		745,                   /* vtotal */
+		719, 745,              /* vblank_start, vblank_end */
+		720, 723,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x720x75
+	{
+		1280, 720,             /* width, height */
+		75, 96000,             /* refresh, dot clock */
+		1695,                  /* htotal */
+		1279, 1695,            /* hblank_start, hblank_end */
+		1351, 1487,            /* hsync_start, hsync_end */
+		751,                   /* vtotal */
+		719, 751,              /* vblank_start, vblank_end */
+		720, 723,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x720x85
+	{
+		1280, 720,             /* width, height */
+		85, 110000,            /* refresh, dot clock */
+		1711,                  /* htotal */
+		1279, 1711,            /* hblank_start, hblank_end */
+		1359, 1495,            /* hsync_start, hsync_end */
+		755,                   /* vtotal */
+		719, 755,              /* vblank_start, vblank_end */
+		720, 723,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x720x100
+	{
+		1280, 720,             /* width, height */
+		100, 131850,           /* refresh, dot clock */
+		1727,                  /* htotal */
+		1279, 1727,            /* hblank_start, hblank_end */
+		1367, 1503,            /* hsync_start, hsync_end */
+		762,                   /* vtotal */
+		719, 762,              /* vblank_start, vblank_end */
+		720, 723,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x768x60
+	{
+		1280, 768,             /* width, height */
+		60, 80136,             /* refresh, dot clock */
+		1679,                  /* htotal */
+		1279, 1679,            /* hblank_start, hblank_end */
+		1343, 1479,            /* hsync_start, hsync_end */
+		794,                   /* vtotal */
+		767, 794,              /* vblank_start, vblank_end */
+		768, 771,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x768x75
+	{
+		1280, 768,             /* width, height */
+		75, 102977,            /* refresh, dot clock */
+		1711,                  /* htotal */
+		1279, 1711,            /* hblank_start, hblank_end */
+		1359, 1495,            /* hsync_start, hsync_end */
+		801,                   /* vtotal */
+		767, 801,              /* vblank_start, vblank_end */
+		768, 771,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x768x85
+	{
+		1280, 768,             /* width, height */
+		85, 118532,            /* refresh, dot clock */
+		1727,                  /* htotal */
+		1279, 1727,            /* hblank_start, hblank_end */
+		1367, 1503,            /* hsync_start, hsync_end */
+		806,                   /* vtotal */
+		767, 806,              /* vblank_start, vblank_end */
+		768, 771,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x960x60
+	{
+		1280, 960,             /* width, height */
+		60, 108000,            /* refresh, dot clock */
+		1799,                  /* htotal */
+		1279, 1799,            /* hblank_start, hblank_end */
+		1375, 1487,            /* hsync_start, hsync_end */
+		999,                   /* vtotal */
+		959, 999,              /* vblank_start, vblank_end */
+		960, 963,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x960x75
+	{
+		1280, 960,             /* width, height */
+		75, 129859,            /* refresh, dot clock */
+		1727,                  /* htotal */
+		1279, 1727,            /* hblank_start, hblank_end */
+		1367, 1503,            /* hsync_start, hsync_end */
+		1001,                  /* vtotal */
+		959, 1001,             /* vblank_start, vblank_end */
+		960, 963,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x960x85
+	{
+		1280, 960,             /* width, height */
+		85, 148500,            /* refresh, dot clock */
+		1727,                  /* htotal */
+		1279, 1727,            /* hblank_start, hblank_end */
+		1343, 1503,            /* hsync_start, hsync_end */
+		1010,                  /* vtotal */
+		959, 1010,             /* vblank_start, vblank_end */
+		960, 963,              /* vsync_start, vsync_end */
+		0x00,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x1024x60
+	{
+		1280, 1024,            /* width, height */
+		60, 108000,            /* refresh, dot clock */
+		1687,                  /* htotal */
+		1279, 1687,            /* hblank_start, hblank_end */
+		1327, 1439,            /* hsync_start, hsync_end */
+		1065,                  /* vtotal */
+		1023, 1065,            /* vblank_start, vblank_end */
+		1024, 1027,            /* vsync_start, vsync_end */
+		0x107,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x1024x70
+	{
+		1280, 1024,            /* width, height */
+		70, 129000,            /* refresh, dot clock */
+		1727,                  /* htotal */
+		1279, 1727,            /* hblank_start, hblank_end */
+		1367, 1503,            /* hsync_start, hsync_end */
+		1065,                  /* vtotal */
+		1023, 1065,            /* vblank_start, vblank_end */
+		1024, 1027,            /* vsync_start, vsync_end */
+		0x107,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x1024x72
+	{
+		1280, 1024,            /* width, height */
+		72, 133000,            /* refresh, dot clock */
+		1727,                  /* htotal */
+		1279, 1727,            /* hblank_start, hblank_end */
+		1367, 1503,            /* hsync_start, hsync_end */
+		1066,                  /* vtotal */
+		1023, 1066,            /* vblank_start, vblank_end */
+		1024, 1027,            /* vsync_start, vsync_end */
+		0x107,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x1024x75
+	{
+		1280, 1024,            /* width, height */
+		75, 135000,            /* refresh, dot clock */
+		1687,                  /* htotal */
+		1279, 1687,            /* hblank_start, hblank_end */
+		1295, 1439,            /* hsync_start, hsync_end */
+		1065,                  /* vtotal */
+		1023, 1065,            /* vblank_start, vblank_end */
+		1024, 1027,            /* vsync_start, vsync_end */
+		0x107,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x1024x85
+	{
+		1280, 1024,            /* width, height */
+		85, 157500,            /* refresh, dot clock */
+		1727,                  /* htotal */
+		1279, 1727,            /* hblank_start, hblank_end */
+		1343, 1503,            /* hsync_start, hsync_end */
+		1071,                  /* vtotal */
+		1023, 1071,            /* vblank_start, vblank_end */
+		1024, 1027,            /* vsync_start, vsync_end */
+		0x107,                 /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x1024x100
+	{
+		1280, 1024,            /* width, height */
+		100, 190960,           /* refresh, dot clock */
+		1759,                  /* htotal */
+		1279, 1759,            /* hblank_start, hblank_end */
+		1375, 1519,            /* hsync_start, hsync_end */
+		1084,                  /* vtotal */
+		1023, 1084,            /* vblank_start, vblank_end */
+		1024, 1027,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1280x1024x120
+	{
+		1280, 1024,            /* width, height */
+		120, 233790,           /* refresh, dot clock */
+		1775,                  /* htotal */
+		1279, 1775,            /* hblank_start, hblank_end */
+		1383, 1527,            /* hsync_start, hsync_end */
+		1096,                  /* vtotal */
+		1023, 1096,            /* vblank_start, vblank_end */
+		1024, 1027,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1366x768x60
+	{
+		1366, 768,             /* width, height */
+		60, 74057,             /* refresh, dot clock */
+		1663,                  /* htotal */
+		1365, 1663,            /* hblank_start, hblank_end */
+		1429, 1557,            /* hsync_start, hsync_end */
+		775,                   /* vtotal */
+		767, 775,              /* vblank_start, vblank_end */
+		768, 769,              /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH |       /* polarity V+ */
+		IGD_HSYNC_HIGH,        /* polarity H+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+
+#ifdef CONFIG_MODE_1400x1050x60
+	{
+		1400, 1050,            /* width, height */
+		60, 122000,            /* refresh, dot clock */
+		1879,                  /* htotal */
+		1399, 1879,            /* hblank_start, hblank_end */
+		1487, 1639,            /* hsync_start, hsync_end */
+		1086,                  /* vtotal */
+		1049, 1086,            /* vblank_start, vblank_end */
+		1050, 1053,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1400x1050x75
+	{
+		1400, 1050,            /* width, height */
+		75, 155851,            /* refresh, dot clock */
+		1895,                  /* htotal */
+		1399, 1895,            /* hblank_start, hblank_end */
+		1495, 1647,            /* hsync_start, hsync_end */
+		1095,                  /* vtotal */
+		1049, 1095,            /* vblank_start, vblank_end */
+		1050, 1053,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1400x1050x85
+	{
+		1400, 1050,            /* width, height */
+		85, 179260,            /* refresh, dot clock */
+		1911,                  /* htotal */
+		1399, 1911,            /* hblank_start, hblank_end */
+		1503, 1655,            /* hsync_start, hsync_end */
+		1102,                  /* vtotal */
+		1049, 1102,            /* vblank_start, vblank_end */
+		1050, 1053,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1600x900x60
+	{
+		1600, 900,             /* width, height */
+		60, 119000,            /* refresh, dot clock */
+		2127,                  /* htotal */
+		1599, 2127,            /* hblank_start, hblank_end */
+		1695, 1863,            /* hsync_start, hsync_end */
+		931,                   /* vtotal */
+		899, 931,              /* vblank_start, vblank_end */
+		900, 903,              /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1600x900x75
+	{
+		1600, 900,             /* width, height */
+		75, 152000,            /* refresh, dot clock */
+		2159,                  /* htotal */
+		1599, 2159,            /* hblank_start, hblank_end */
+		1703, 1879,            /* hsync_start, hsync_end */
+		939,                   /* vtotal */
+		899, 939,              /* vblank_start, vblank_end */
+		900, 903,              /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1600x900x85
+	{
+		1600, 900,             /* width, height */
+		85, 175000,            /* refresh, dot clock */
+		2175,                  /* htotal */
+		1599, 2175,            /* hblank_start, hblank_end */
+		1711, 1887,            /* hsync_start, hsync_end */
+		944,                   /* vtotal */
+		899, 944,              /* vblank_start, vblank_end */
+		900, 903,              /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1600x900x100
+	{
+		1600, 900,             /* width, height */
+		100, 208900,           /* refresh, dot clock */
+		2191,                  /* htotal */
+		1599, 2191,            /* hblank_start, hblank_end */
+		1719, 1895,            /* hsync_start, hsync_end */
+		952,                   /* vtotal */
+		899, 952,              /* vblank_start, vblank_end */
+		900, 903,              /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1600x900x120
+	{
+		1600, 900,             /* width, height */
+		120, 255686,           /* refresh, dot clock */
+		2207,                  /* htotal */
+		1599, 2207,            /* hblank_start, hblank_end */
+		1727, 1903,            /* hsync_start, hsync_end */
+		964,                   /* vtotal */
+		899, 964,              /* vblank_start, vblank_end */
+		900, 903,              /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1600x1200x60
+	{
+		1600, 1200,            /* width, height */
+		60, 162000,            /* refresh, dot clock */
+		2159,                  /* htotal */
+		1599, 2159,            /* hblank_start, hblank_end */
+		1663, 1855,            /* hsync_start, hsync_end */
+		1249,                  /* vtotal */
+		1199, 1249,            /* vblank_start, vblank_end */
+		1200, 1203,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1600x1200x65
+	{
+		1600, 1200,            /* width, height */
+		65, 175500,            /* refresh, dot clock */
+		2159,                  /* htotal */
+		1599, 2159,            /* hblank_start, hblank_end */
+		1663, 1855,            /* hsync_start, hsync_end */
+		1249,                  /* vtotal */
+		1199, 1249,            /* vblank_start, vblank_end */
+		1200, 1203,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1600x1200x70
+	{
+		1600, 1200,            /* width, height */
+		70, 189000,            /* refresh, dot clock */
+		2159,                  /* htotal */
+		1599, 2159,            /* hblank_start, hblank_end */
+		1663, 1855,            /* hsync_start, hsync_end */
+		1249,                  /* vtotal */
+		1199, 1249,            /* vblank_start, vblank_end */
+		1200, 1203,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1600x1200x72
+	{
+		1600, 1200,            /* width, height */
+		72, 195000,            /* refresh, dot clock */
+		2175,                  /* htotal */
+		1599, 2175,            /* hblank_start, hblank_end */
+		1711, 1887,            /* hsync_start, hsync_end */
+		1250,                  /* vtotal */
+		1199, 1250,            /* vblank_start, vblank_end */
+		1200, 1203,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1600x1200x75
+	{
+		1600, 1200,            /* width, height */
+		75, 202500,            /* refresh, dot clock */
+		2159,                  /* htotal */
+		1599, 2159,            /* hblank_start, hblank_end */
+		1663, 1855,            /* hsync_start, hsync_end */
+		1249,                  /* vtotal */
+		1199, 1249,            /* vblank_start, vblank_end */
+		1200, 1203,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1600x1200x85
+	{
+		1600, 1200,            /* width, height */
+		85, 229500,            /* refresh, dot clock */
+		2159,                  /* htotal */
+		1599, 2159,            /* hblank_start, hblank_end */
+		1663, 1855,            /* hsync_start, hsync_end */
+		1249,                  /* vtotal */
+		1199, 1249,            /* vblank_start, vblank_end */
+		1200, 1203,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_HSYNC_HIGH|        /* polarity H+ */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1600x1200x100
+	{
+		1600, 1200,            /* width, height */
+		100, 280640,           /* refresh, dot clock */
+		2207,                  /* htotal */
+		1599, 2207,            /* hblank_start, hblank_end */
+		1727, 1903,            /* hsync_start, hsync_end */
+		1270,                  /* vtotal */
+		1199, 1270,            /* vblank_start, vblank_end */
+		1200, 1203,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1600x1200x120
+	{
+		1600, 1200,            /* width, height */
+		120, 343210,           /* refresh, dot clock */
+		2223,                  /* htotal */
+		1599, 2223,            /* hblank_start, hblank_end */
+		1735, 1911,            /* hsync_start, hsync_end */
+		1285,                  /* vtotal */
+		1199, 1285,            /* vblank_start, vblank_end */
+		1200, 1203,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1856x1392x60
+	{
+		1856, 1392,            /* width, height */
+		60, 218250,            /* refresh, dot clock */
+		2527,                  /* htotal */
+		1855, 2527,            /* hblank_start, hblank_end */
+		1951, 2175,            /* hsync_start, hsync_end */
+		1438,                  /* vtotal */
+		1391, 1438,            /* vblank_start, vblank_end */
+		1392, 1395,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1856x1392x75
+	{
+		1856, 1392,            /* width, height */
+		75, 288000,            /* refresh, dot clock */
+		2559,                  /* htotal */
+		1855, 2559,            /* hblank_start, hblank_end */
+		1983, 2207,            /* hsync_start, hsync_end */
+		1499,                  /* vtotal */
+		1391, 1499,            /* vblank_start, vblank_end */
+		1392, 1395,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1920x1080x50
+	{
+		1920, 1080,            /* width, height */
+		50, 141446,            /* refresh, dot clock */
+		2543,                  /* htotal */
+		1919, 2543,            /* hblank_start, hblank_end */
+		2031, 2231,            /* hsync_start, hsync_end */
+		1111,                  /* vtotal */
+		1079, 1111,            /* vblank_start, vblank_end */
+		1080, 1083,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1920x1080x60
+	{
+		1920, 1080,            /* width, height */
+		60, 172800,            /* refresh, dot clock */
+		2575,                  /* htotal */
+		1919, 2575,            /* hblank_start, hblank_end */
+		2039, 2247,            /* hsync_start, hsync_end */
+		1117,                  /* vtotal */
+		1079, 1117,            /* vblank_start, vblank_end */
+		1080, 1083,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1920x1080x75
+	{
+		1920, 1080,            /* width, height */
+		75, 220640,            /* refresh, dot clock */
+		2607,                  /* htotal */
+		1919, 2607,            /* hblank_start, hblank_end */
+		2055, 2263,            /* hsync_start, hsync_end */
+		1127,                  /* vtotal */
+		1079, 1127,            /* vblank_start, vblank_end */
+		1080, 1083,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1920x1080x85
+	{
+		1920, 1080,            /* width, height */
+		85, 252930,            /* refresh, dot clock */
+		2623,                  /* htotal */
+		1919, 2623,            /* hblank_start, hblank_end */
+		2063, 2271,            /* hsync_start, hsync_end */
+		1133,                  /* vtotal */
+		1079, 1133,            /* vblank_start, vblank_end */
+		1080, 1083,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1920x1080x100
+	{
+		1920, 1080,            /* width, height */
+		100, 302020,           /* refresh, dot clock */
+		2639,                  /* htotal */
+		1919, 2639,            /* hblank_start, hblank_end */
+		2071, 2279,            /* hsync_start, hsync_end */
+		1143,                  /* vtotal */
+		1079, 1143,            /* vblank_start, vblank_end */
+		1080, 1083,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1920x1200x60
+	{
+		1920, 1200,            /* width, height */
+		60, 193156,            /* refresh, dot clock */
+		2591,                  /* htotal */
+		1919, 2591,            /* hblank_start, hblank_end */
+		2047, 2255,            /* hsync_start, hsync_end */
+		1241,                  /* vtotal */
+		1199, 1241,            /* vblank_start, vblank_end */
+		1200, 1203,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1920x1200x75
+	{
+		1920, 1200,            /* width, height */
+		75, 246590,            /* refresh, dot clock */
+		2623,                  /* htotal */
+		1919, 2623,            /* hblank_start, hblank_end */
+		2063, 2271,            /* hsync_start, hsync_end */
+		1252,                  /* vtotal */
+		1199, 1252,            /* vblank_start, vblank_end */
+		1200, 1203,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1920x1440x60
+	{
+		1920, 1440,            /* width, height */
+		60, 234000,            /* refresh, dot clock */
+		2599,                  /* htotal */
+		1919, 2599,            /* hblank_start, hblank_end */
+		2047, 2255,            /* hsync_start, hsync_end */
+		1499,                  /* vtotal */
+		1439, 1499,            /* vblank_start, vblank_end */
+		1440, 1443,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1920x1440x75
+	{
+		1920, 1440,            /* width, height */
+		75, 297000,            /* refresh, dot clock */
+		2639,                  /* htotal */
+		1919, 2639,            /* hblank_start, hblank_end */
+		2063, 2287,            /* hsync_start, hsync_end */
+		1499,                  /* vtotal */
+		1439, 1499,            /* vblank_start, vblank_end */
+		1440, 1443,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_1920x1440x85
+	{
+		1920, 1440,            /* width, height */
+		85, 341350,            /* refresh, dot clock */
+		2655,                  /* htotal */
+		1919, 2655,            /* hblank_start, hblank_end */
+		2071, 2287,            /* hsync_start, hsync_end */
+		1511,                  /* vtotal */
+		1439, 1511,            /* vblank_start, vblank_end */
+		1440, 1443,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_2048x1536x60
+	{
+		2048, 1536,            /* width, height */
+		60, 266950,            /* refresh, dot clock */
+		2799,                  /* htotal */
+		2047, 2799,            /* hblank_start, hblank_end */
+		2199, 2423,            /* hsync_start, hsync_end */
+		1588,                  /* vtotal */
+		1535, 1588,            /* vblank_start, vblank_end */
+		1536, 1539,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_MODE_2048x1536x75
+	{
+		2048, 1536,            /* width, height */
+		75, 340480,            /* refresh, dot clock */
+		2831,                  /* htotal */
+		2047, 2831,            /* hblank_start, hblank_end */
+		2215, 2439,            /* hsync_start, hsync_end */
+		1602,                  /* vtotal */
+		1535, 1602,            /* vblank_start, vblank_end */
+		1536, 1539,            /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE|  /* mode info flags */
+		IGD_VSYNC_HIGH,        /* polarity V+ */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+	PD_TIMING_TABLE_END
+};
+
+int crt_timing_table_size = sizeof(crt_timing_table);
+
+/*---------------------------------------------------------------------------
+ * Timing tables for VGA modes
+ *---------------------------------------------------------------------------
+ */
+igd_timing_info_t vga_timing_table[] =
+{
+	{   /* VGA Mode 0 */
+		320, 200,              /* width, height */
+		60, 25175,             /* refresh, dot clock */
+		399,                   /* htotal */
+		319, 383,              /* hblank_start, hblank_end */
+		343, 383,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		405, 440,              /* vblank_start, vblank_end */
+		411, 413,              /* vsync_start, vsync_end */
+		0x00,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_MODE_TEXT |
+		IGD_LINE_DOUBLE |
+		IGD_PIXEL_DOUBLE |
+		IGD_VSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 1 */
+		320, 200,              /* width, height */
+		60, 25175,             /* refresh, dot clock */
+		399,                   /* htotal */
+		319, 383,              /* hblank_start, hblank_end */
+		343, 383,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		405, 440,              /* vblank_start, vblank_end */
+		411, 413,              /* vsync_start, vsync_end */
+		0x01,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_MODE_TEXT |
+		IGD_LINE_DOUBLE |
+		IGD_PIXEL_DOUBLE |
+		IGD_VSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 2 */
+		640, 200,              /* width, height */
+		70, 25175,             /* refresh, dot clock */
+		799,                   /* htotal */
+		639, 783,              /* hblank_start, hblank_end */
+		679, 775,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		405, 440,              /* vblank_start, vblank_end */
+		411, 413,              /* vsync_start, vsync_end */
+		0x02,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_MODE_TEXT |
+		IGD_LINE_DOUBLE |
+		IGD_VSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 3 */
+		640, 200,              /* width, height */
+		70, 25175,             /* refresh, dot clock */
+		799,                   /* htotal */
+		639, 783,              /* hblank_start, hblank_end */
+		679, 775,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		405, 440,              /* vblank_start, vblank_end */
+		411, 413,              /* vsync_start, vsync_end */
+		0x03,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_MODE_TEXT |
+		IGD_LINE_DOUBLE |
+		IGD_VSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 4 */
+		320, 200,              /* width, height */
+		60, 25175,             /* refresh, dot clock */
+		399,                   /* htotal */
+		319, 383,              /* hblank_start, hblank_end */
+		343, 383,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		405, 440,              /* vblank_start, vblank_end */
+		411, 413,              /* vsync_start, vsync_end */
+		0x04,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_LINE_DOUBLE |
+		IGD_VSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 5 */
+		320, 200,              /* width, height */
+		60, 25175,             /* refresh, dot clock */
+		399,                   /* htotal */
+		319, 383,              /* hblank_start, hblank_end */
+		343, 383,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		405, 440,              /* vblank_start, vblank_end */
+		411, 413,              /* vsync_start, vsync_end */
+		0x05,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_LINE_DOUBLE |
+		IGD_VSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 6 */
+		640, 200,              /* width, height */
+		60, 25175,             /* refresh, dot clock */
+		799,                   /* htotal */
+		639, 784,              /* hblank_start, hblank_end */
+		671, 767,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		405, 440,              /* vblank_start, vblank_end */
+		411, 413,              /* vsync_start, vsync_end */
+		0x06,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_LINE_DOUBLE |
+		IGD_VSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 7 */
+		720, 350,              /* width, height */
+		60, 28322,             /* refresh, dot clock */
+		899,                   /* htotal */
+		719, 881,              /* hblank_start, hblank_end */
+		764, 872,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		354, 441,              /* vblank_start, vblank_end */
+		386, 388,              /* vsync_start, vsync_end */
+		0x07,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_MODE_TEXT |
+		IGD_HSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode d */
+		320, 200,              /* width, height */
+		60, 25175,             /* refresh, dot clock */
+		399,                   /* htotal */
+		319, 383,              /* hblank_start, hblank_end */
+		343, 383,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		405, 440,              /* vblank_start, vblank_end */
+		411, 413,              /* vsync_start, vsync_end */
+		0x0d,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_LINE_DOUBLE |
+		IGD_PIXEL_DOUBLE |
+		IGD_VSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode e */
+		640, 200,              /* width, height */
+		60, 25175,             /* refresh, dot clock */
+		799,                   /* htotal */
+		639, 783,              /* hblank_start, hblank_end */
+		671, 767,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		405, 440,              /* vblank_start, vblank_end */
+		411, 413,              /* vsync_start, vsync_end */
+		0x0e,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_LINE_DOUBLE |
+		IGD_VSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode f */
+		640, 350,              /* width, height */
+		60, 25175,             /* refresh, dot clock */
+		799,                   /* htotal */
+		639, 783,              /* hblank_start, hblank_end */
+		671, 767,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		354, 441,              /* vblank_start, vblank_end */
+		386, 388,              /* vsync_start, vsync_end */
+		0x11,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_HSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 10 */
+		640, 350,              /* width, height */
+		60, 25175,             /* refresh, dot clock */
+		799,                   /* htotal */
+		639, 783,              /* hblank_start, hblank_end */
+		671, 767,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		354, 441,              /* vblank_start, vblank_end */
+		386, 388,              /* vsync_start, vsync_end */
+		0x12,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_HSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 0* */
+		320, 350,              /* width, height */
+		60, 25175,             /* refresh, dot clock */
+		399,                   /* htotal */
+		319, 383,              /* hblank_start, hblank_end */
+		343, 383,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		354, 441,              /* vblank_start, vblank_end */
+		386, 388,              /* vsync_start, vsync_end */
+		0x13,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_PIXEL_DOUBLE |
+		IGD_MODE_TEXT |
+		IGD_HSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 1* */
+		320, 350,              /* width, height */
+		60, 25175,             /* refresh, dot clock */
+		399,                   /* htotal */
+		319, 383,              /* hblank_start, hblank_end */
+		343, 383,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		354, 441,              /* vblank_start, vblank_end */
+		386, 388,              /* vsync_start, vsync_end */
+		0x14,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_PIXEL_DOUBLE |
+		IGD_MODE_TEXT |
+		IGD_HSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 2* */
+		640, 350,              /* width, height */
+		70, 25175,             /* refresh, dot clock */
+		799,                   /* htotal */
+		639, 783,              /* hblank_start, hblank_end */
+		679, 775,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		354, 441,              /* vblank_start, vblank_end */
+		386, 388,              /* vsync_start, vsync_end */
+		0x15,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_MODE_TEXT |
+		IGD_HSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 3* */
+		640, 350,              /* width, height */
+		70, 25175,             /* refresh, dot clock */
+		799,                   /* htotal */
+		639, 783,              /* hblank_start, hblank_end */
+		679, 775,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		354, 441,              /* vblank_start, vblank_end */
+		386, 388,              /* vsync_start, vsync_end */
+		0x16,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_MODE_TEXT |
+		IGD_HSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 0+,1+ */
+		360, 400,              /* width, height */
+		60, 28322,             /* refresh, dot clock */
+		449,                   /* htotal */
+		359, 431,              /* hblank_start, hblank_end */
+		386, 431,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		405, 440,              /* vblank_start, vblank_end */
+		411, 413,              /* vsync_start, vsync_end */
+		0x17,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_PIXEL_DOUBLE |
+		IGD_MODE_TEXT |
+		IGD_VSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 2+,3+ */
+		720, 400,              /* width, height */
+		70, 28322,             /* refresh, dot clock */
+		899,                   /* htotal */
+		719, 881,              /* hblank_start, hblank_end */
+		764, 872,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		405, 440,              /* vblank_start, vblank_end */
+		411, 413,              /* vsync_start, vsync_end */
+		0x18,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_MODE_TEXT |
+		IGD_VSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 7+ */
+		720, 400,              /* width, height */
+		60, 28322,             /* refresh, dot clock */
+		899,                   /* htotal */
+		719, 881,              /* hblank_start, hblank_end */
+		764, 872,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		405, 440,              /* vblank_start, vblank_end */
+		411, 413,              /* vsync_start, vsync_end */
+		0x19,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_MODE_TEXT |
+		IGD_VSYNC_HIGH |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 11 */
+		640, 480,              /* width, height */
+		60, 25175,             /* refresh, dot clock */
+		799,                   /* htotal */
+		639, 783,              /* hblank_start, hblank_end */
+		671, 767,              /* hsync_start, hsync_end */
+		524,                   /* vtotal */
+		486, 515,              /* vblank_start, vblank_end */
+		489, 491,              /* vsync_start, vsync_end */
+		0x1A,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 12 */
+		640, 480,              /* width, height */
+		60, 25175,             /* refresh, dot clock */
+		799,                   /* htotal */
+		639, 783,              /* hblank_start, hblank_end */
+		671, 767,              /* hsync_start, hsync_end */
+		524,                   /* vtotal */
+		486, 515,              /* vblank_start, vblank_end */
+		489, 491,              /* vsync_start, vsync_end */
+		0x1B,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+	{   /* VGA Mode 13 */
+		320, 200,              /* width, height */
+		60, 25175,             /* refresh, dot clock */
+		799,                   /* htotal */
+		639, 783,              /* hblank_start, hblank_end */
+		671, 767,              /* hsync_start, hsync_end */
+		448,                   /* vtotal */
+		405, 440,              /* vblank_start, vblank_end */
+		411, 413,              /* vsync_start, vsync_end */
+		0x1C,                  /* mode number */
+		IGD_MODE_VESA |        /* VESA/VGA mode */
+		IGD_LINE_DOUBLE |
+		IGD_PIXEL_DOUBLE |
+		IGD_MODE_SUPPORTED |
+		IGD_SCAN_PROGRESSIVE,  /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+
+	PD_TIMING_TABLE_END
+};
+
+/* CEA standard timings: Get them from CEA-861. This is following DPG.
+   We will replace the mode number to CEA*/
+igd_timing_info_t cea_timing_table[] =
+{
+#ifdef CONFIG_CEA_MODE_640x480px60
+	{
+		640, 480,              /* width, height */
+		60, 25200,             /* refresh, dot clock */
+		800,                   /* htotal */
+		640, 799,              /* hblank_start, hblank_end */
+		656, 751,              /* hsync_start, hsync_end */
+		525,                   /* vtotal */
+		480, 524,              /* vblank_start, vblank_end */
+		490, 491,              /* vsync_start, vsync_end */
+		1,					   /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE |
+		PD_MODE_CEA,		   /* mode info flags */
+		0, 0,                  /* x, y offset */
+		0,				   /* device dependant */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_CEA_MODE_720x480px60
+	{
+		720, 480,              /* width, height */
+		60, 27000,             /* refresh, dot clock */
+		858,                   /* htotal */
+		720, 857,              /* hblank_start, hblank_end */
+		736, 797,              /* hsync_start, hsync_end */
+		525,                   /* vtotal */
+		480, 524,              /* vblank_start, vblank_end */
+		489, 494,              /* vsync_start, vsync_end */
+		2,					   /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE |
+		PD_MODE_CEA,		   /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_CEA_MODE_720x480p_ax60
+	{
+		720, 480,              /* width, height */
+		60, 27000,             /* refresh, dot clock */
+		858,                   /* htotal */
+		720, 857,              /* hblank_start, hblank_end */
+		736, 797,              /* hsync_start, hsync_end */
+		525,                   /* vtotal */
+		480, 524,              /* vblank_start, vblank_end */
+		489, 494,              /* vsync_start, vsync_end */
+		3,                     /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE |
+		PD_MODE_CEA |          /* mode info flags */
+		PD_ASPECT_16_9,        /* Aspect ratio 16:9 */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_CEA_MODE_720x576px50
+	{
+		720, 576,              /* width, height */
+		50, 27000,             /* refresh, dot clock */
+		864,                   /* htotal */
+		720, 863,              /* hblank_start, hblank_end */
+		732, 795,              /* hsync_start, hsync_end */
+		625,                   /* vtotal */
+		575, 624,              /* vblank_start, vblank_end */
+		581, 585,              /* vsync_start, vsync_end */
+		17,                    /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE |
+		PD_MODE_CEA,		   /* mode info flags */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_CEA_MODE_720x576p_ax50
+	{
+		720, 576,              /* width, height */
+		50, 27000,             /* refresh, dot clock */
+		864,                   /* htotal */
+		720, 863,              /* hblank_start, hblank_end */
+		732, 795,              /* hsync_start, hsync_end */
+		625,                   /* vtotal */
+		575, 624,              /* vblank_start, vblank_end */
+		581, 585,              /* vsync_start, vsync_end */
+		18,                    /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE |
+		PD_MODE_CEA |		   /* mode info flags */
+		PD_ASPECT_16_9,        /* Aspect ratio 16:9 */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_CEA_MODE_1280x720p_ax50
+	{
+		1280, 720,             /* width, height */
+		50, 74250,             /* refresh, dot clock */
+		1980,                  /* htotal */
+		1280, 1979,            /* hblank_start, hblank_end */
+		1720, 1759,            /* hsync_start, hsync_end */
+		750,                   /* vtotal */
+		720, 749,              /* vblank_start, vblank_end */
+		725, 729,              /* vsync_start, vsync_end */
+		19,                    /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE |
+		PD_MODE_CEA |		   /* mode info flags */
+		PD_ASPECT_16_9,        /* Aspect ratio 16:9 */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_CEA_MODE_1280x720p_ax60
+	{
+		1280, 720,             /* width, height */
+		60, 74250,             /* refresh, dot clock */
+		1650,                  /* htotal */
+		1280, 1649,            /* hblank_start, hblank_end */
+		1390, 1429,            /* hsync_start, hsync_end */
+		750,                   /* vtotal */
+		720, 749,              /* vblank_start, vblank_end */
+		725, 729,              /* vsync_start, vsync_end */
+		4,                     /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE | /* mode info flags */
+		IGD_VSYNC_HIGH |
+		PD_MODE_CEA |		   /* polarity V+ */
+		PD_ASPECT_16_9,        /* Aspect ratio 16:9 */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+/* KIV. Not proper timimgs, rerefer to DPG updates */
+#ifdef CONFIG_CEA_MODE_1920x1080p_ax50
+	{
+		1920, 1080,            /* width, height */
+		50, 148500,            /* refresh, dot clock */
+		2640,                  /* htotal */
+		1920, 2639,            /* hblank_start, hblank_end */
+		2448, 2491,            /* hsync_start, hsync_end */
+		1125,                  /* vtotal */
+		1080, 1124,            /* vblank_start, vblank_end */
+		1084, 1088,            /* vsync_start, vsync_end */
+		31,                    /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE | /* mode info flags */
+		IGD_VSYNC_HIGH |
+		PD_MODE_CEA |		   /* polarity V+ */
+		PD_ASPECT_16_9,        /* Aspect ratio 16:9 */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_CEA_MODE_1920x1080p_ax60
+	{
+		1920, 1080,            /* width, height */
+		60, 148500,            /* refresh, dot clock */
+		2200,                  /* htotal */
+		1920, 2199,            /* hblank_start, hblank_end */
+		2008, 2051,            /* hsync_start, hsync_end */
+		1125,                  /* vtotal */
+		1080, 1124,            /* vblank_start, vblank_end */
+		1084, 1088,            /* vsync_start, vsync_end */
+		16,                     /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_PROGRESSIVE | /* mode info flags */
+		IGD_VSYNC_HIGH |
+		PD_MODE_CEA |	       /* polarity V+ */
+		PD_ASPECT_16_9,        /* Aspect ratio 16:9 */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_CEA_MODE_1920x1080i_ax50
+	{
+		1920, 1080,            /* width, height */
+		25, 74250,             /* refresh, dot clock */
+		2640,                  /* htotal */
+		1920, 2639,            /* hblank_start, hblank_end */
+		2448, 2491,            /* hsync_start, hsync_end */
+		1124,                  /* vtotal */
+		1080, 1123,            /* vblank_start, vblank_end */
+		1084, 1093,            /* vsync_start, vsync_end */
+		20,					   /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_INTERLACE |   /* mode info flags */
+		IGD_VSYNC_HIGH |
+		PD_MODE_CEA |		   /* polarity V+ */
+		PD_ASPECT_16_9,        /* Aspect ratio 16:9 */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+#ifdef CONFIG_CEA_MODE_1920x1080i_ax60
+	{
+		1920, 1080,            /* width, height */
+		30, 74250,             /* refresh, dot clock */
+		2200,                  /* htotal */
+		1920, 2199,            /* hblank_start, hblank_end */
+		2008, 2051,            /* hsync_start, hsync_end */
+		1124,                  /* vtotal */
+		1080, 1123,            /* vblank_start, vblank_end */
+		1084, 1093,            /* vsync_start, vsync_end */
+		5,					   /* mode number */
+		PD_MODE_SUPPORTED |    /* enable the mode */
+		IGD_SCAN_INTERLACE |   /* mode info flags */
+		IGD_VSYNC_HIGH |
+		PD_MODE_CEA |		   /* polarity V+ */
+		PD_ASPECT_16_9,        /* Aspect ratio 16:9 */
+		0, 0,                  /* x, y offset */
+		NULL,                  /* mode extension pointer */
+		0,				   /* device dependant */
+		0				   /* device dependant */
+	},
+#endif
+	PD_TIMING_TABLE_END
+};
+
+#ifndef CONFIG_MICRO
+int cea_timing_table_size = sizeof(cea_timing_table);
+
+/* CEA timings for parsing purpose */
+type_std_t cea_std_lookup[] =
+{
+	{  640,    400,   60,    0 },
+	{  720,    480,   60,    0 },
+	{  720,    480,   60,    PD_ASPECT_16_9 },
+	{ 1280,    720,   60,    PD_ASPECT_16_9 },
+	{ 1920,   1080,   60,    PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+	{  720,    480,   60,    PD_SCAN_INTERLACE },
+	{  720,    480,   60,    PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+	{  720,    240,   60,    0 },
+
+	{  720,    240,   60,    PD_ASPECT_16_9 },
+	{ 2880,    480,   60,    PD_SCAN_INTERLACE },
+	{ 2880,    480,   60,    PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+	{ 2880,    240,   60,    0 },
+	{ 2880,    240,   60,    PD_ASPECT_16_9 },
+	{ 1440,    480,   60,    0 },
+	{ 1440,    480,   60,    PD_ASPECT_16_9 },
+	{ 1920,   1080,   60,    PD_ASPECT_16_9 },
+
+	{  720,    576,   50,    0 },
+	{  720,    576,   50,    PD_ASPECT_16_9 },
+	{ 1280,    720,   50,    PD_ASPECT_16_9 },
+	{ 1920,   1080,   50,    PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+	{  720,    576,   50,    PD_SCAN_INTERLACE },
+	{  720,    576,   50,    PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+	{  720,    288,   50,    0 },
+	{  720,    288,   50,    PD_ASPECT_16_9 },
+
+	{ 2880,    576,   50,    PD_SCAN_INTERLACE },
+	{ 2880,    576,   50,    PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+	{ 2880,    288,   50,    0 },
+	{ 2880,    288,   50,    PD_ASPECT_16_9 },
+	{ 1440,    576,   50,    0 },
+	{ 1440,    576,   50,    PD_ASPECT_16_9 },
+	{ 1920,   1080,   50,    PD_ASPECT_16_9 },
+	{ 1920,   1080,   24,    PD_ASPECT_16_9 },
+
+	{ 1920,   1080,   25,    PD_ASPECT_16_9 },
+	{ 1920,   1080,   30,    PD_ASPECT_16_9 },
+	{ 2880,    480,   60,    0 },
+	{ 2880,    480,   60,    PD_ASPECT_16_9 },
+	{ 2880,    576,   50,    0 },
+	{ 2880,    576,   50,    PD_ASPECT_16_9 },
+	{ 1920,   1080,   50,    PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+	{ 1920,   1080,   100,   PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+
+	{ 1280,    720,   100,   PD_ASPECT_16_9 },
+	{  720,    576,   100,   0 },
+	{  720,    576,   100,   PD_ASPECT_16_9 },
+	{  720,    576,   100,   PD_SCAN_INTERLACE },
+	{  720,    576,   100,   PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+	{ 1920,   1080,   120,   PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+	{ 1280,    720,   120,   PD_ASPECT_16_9 },
+	{  720,    480,   120,   0 },
+
+	{  720,    480,   120,   PD_ASPECT_16_9 },
+	{  720,    480,   120,   PD_SCAN_INTERLACE },
+	{  720,    480,   120,   PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+	{  720,    576,   200,   0 },
+	{  720,    576,   200,   PD_ASPECT_16_9 },
+	{  720,    576,   200,   PD_SCAN_INTERLACE },
+	{  720,    576,   200,   PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+	{  720,    480,   240,   0 },
+
+	{  720,    480,   240,   PD_ASPECT_16_9 },
+	{  720,    480,   240,   PD_SCAN_INTERLACE },
+	{  720,    480,   240,   PD_SCAN_INTERLACE | PD_ASPECT_16_9 },
+	{ 1280,    720,   24,    PD_ASPECT_16_9 },
+	{ 1280,    720,   25,    PD_ASPECT_16_9 },
+	{ 1280,    720,   30,    PD_ASPECT_16_9 },
+};
+
+int cea_std_lookup_size = sizeof(cea_std_lookup)/sizeof(type_std_t);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/cmn/pd_init_all.c b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/pd_init_all.c
new file mode 100644
index 0000000..ba70fc8
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/pd_init_all.c
@@ -0,0 +1,215 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pd_init_all.c
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file controls the port drivers that are initialized as part of
+ *  the HAL init. These must be statically linked with the HAL.
+ *  NOTE: This file is visible to customers. It is used in source form as
+ *  part of the vBIOS build procedure.
+ *-----------------------------------------------------------------------------
+ */
+
+#include "config.h"
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/* Enable Analog (CRT) port driver */
+#ifdef CONFIG_LINK_PD_ANALOG
+extern int analog_init(void *handle);
+#define ANALOG_INIT(handle)  analog_init(handle)
+#else
+#define ANALOG_INIT(handle)  0
+#endif
+
+/* Enable Silicon Image 154/164 FP port driver */
+#ifdef CONFIG_LINK_PD_SII164
+extern int sii164_init(void *handle);
+#define SII164_INIT(handle)  sii164_init(handle)
+#else
+#define SII164_INIT(handle)  0
+#endif
+
+/* Enable Texas Instruments 410 FP port driver */
+#ifdef CONFIG_LINK_PD_TI410
+extern int ti410_init(void *handle);
+#define TI410_INIT(handle)  ti410_init(handle)
+#else
+#define TI410_INIT(handle)  0
+#endif
+
+/* Enable Chrontel 7009 TMDS & TVOut port driver */
+#ifdef CONFIG_LINK_PD_CH7009
+extern int ch7009_init(void *handle);
+#define CH7009_INIT(handle)  ch7009_init(handle)
+#else
+#define CH7009_INIT(handle)  0
+#endif
+
+/* Enable National Semiconductor 2501 LVDS port driver */
+#ifdef CONFIG_LINK_PD_NS2501
+extern int ns2501_init(void *handle);
+#define NS2501_INIT(handle)  ns2501_init(handle)
+#else
+#define NS2501_INIT(handle)  0
+#endif
+
+/* Enable TL955 port driver */
+#ifdef CONFIG_LINK_PD_TL955
+extern int tl955_init(void *handle);
+#define TL955_INIT(handle)  tl955_init(handle)
+#else
+#define TL955_INIT(handle)  0
+#endif
+
+/* Enable Th164 port driver */
+#ifdef CONFIG_LINK_PD_TH164
+extern int th164_init(void *handle);
+#define TH164_INIT(handle)  th164_init(handle)
+#else
+#define TH164_INIT(handle)  0
+#endif
+
+/* Enable FS454 port driver */
+#ifdef CONFIG_LINK_PD_FS454
+extern int fs454_init(void *handle);
+#define FS454_INIT(handle)  fs454_init(handle)
+#else
+#define FS454_INIT(handle)  0
+#endif
+
+/* Enable NS387/389 port driver */
+#ifdef CONFIG_LINK_PD_NS387
+extern int ns387_init(void *handle);
+#define NS387_INIT(handle)  ns387_init(handle)
+#else
+#define NS387_INIT(handle)  0
+#endif
+
+/* Enable connexant port driver */
+#ifdef CONFIG_LINK_PD_CX873
+extern int cx873_init(void *handle);
+#define CX873_INIT(handle)  cx873_init(handle)
+#else
+#define CX873_INIT(handle)  0
+#endif
+
+/* Enable Internal LVDS port driver */
+#ifdef CONFIG_LINK_PD_LVDS
+extern int lvds_init(void *handle);
+#define LVDS_INIT(handle)  lvds_init(handle)
+#else
+#define LVDS_INIT(handle)  0
+#endif
+
+/* Enable SDVO port driver */
+#ifdef CONFIG_LINK_PD_SDVO
+extern int sdvo_init(void *handle);
+#define SDVO_INIT(handle)  sdvo_init(handle)
+#else
+#define SDVO_INIT(handle)  0
+#endif
+
+/* Enable Integrated TV port driver for NAPA */
+#ifdef CONFIG_LINK_PD_TV
+extern int tv_init(void *handle);
+#define TV_INIT(handle)  tv_init(handle)
+#else
+#define TV_INIT(handle)  0
+#endif
+
+/* Enable FS460 port driver */
+#ifdef CONFIG_LINK_PD_FS460
+extern int fs460_init(void *handle);
+#define FS460_INIT(handle)  fs460_init(handle)
+#else
+#define FS460_INIT(handle)  0
+#endif
+
+/* Enable FS450 port driver */
+#ifdef CONFIG_LINK_PD_FS450
+extern int fs450_init(void *handle);
+#define FS450_INIT(handle)  fs450_init(handle)
+#else
+#define FS450_INIT(handle)  0
+#endif
+
+/* Enable Chrontel 7017 LVDS & TVOut port driver */
+#ifdef CONFIG_LINK_PD_CH7017
+extern int ch7017_init(void *handle);
+#define CH7017_INIT(handle)  ch7017_init(handle)
+#else
+#define CH7017_INIT(handle)  0
+#endif
+
+/* Enable internal HDMI port driver */
+#ifdef CONFIG_LINK_PD_HDMI
+extern int hdmi_init(void *handle);
+#define HDMI_INIT(handle)  hdmi_init(handle)
+#else
+#define HDMI_INIT(handle)  0
+#endif
+
+/* Enable Chrontel CH7036  port driver */
+#ifdef CONFIG_LINK_PD_CH7036
+extern int ch7036_init(void *handle);
+#define CH7036_INIT(handle)  ch7036_init(handle)
+#else
+#define CH7036_INIT(handle)  0
+#endif
+
+
+/*!
+ *
+ * @param handle
+ *
+ * @return 0
+ */
+int pi_init_all(void *handle)
+{
+	int ret;
+
+	ret = ANALOG_INIT(handle);
+	ret = CH7009_INIT(handle);
+	ret = SII164_INIT(handle);
+	ret = NS2501_INIT(handle);
+	ret = TH164_INIT(handle);
+	ret = NS387_INIT(handle);
+	ret = FS454_INIT(handle);
+	ret = CH7017_INIT(handle);
+	ret = SDVO_INIT(handle);
+	ret = TI410_INIT(handle);
+	ret = TV_INIT(handle);
+	ret = HDMI_INIT(handle);
+	ret = CH7036_INIT(handle);
+	ret = LVDS_INIT(handle); /*LVDS need to be initiate only after CH7036.*/
+	/* ret = PD000_INIT(handle); */
+
+	return 0;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/cmn/pi.c b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/pi.c
new file mode 100755
index 0000000..8eca6c7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/cmn/pi.c
@@ -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/drivers/gpu/drm/emgd/emgd/display/pi/plb/i2c_plb.c b/drivers/gpu/drm/emgd/emgd/display/pi/plb/i2c_plb.c
new file mode 100644
index 0000000..7021e34
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/plb/i2c_plb.c
@@ -0,0 +1,943 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: i2c_plb.c
+ * $Revision: 1.14 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.dpd
+
+#include <io.h>
+#include <memory.h>
+#include <sched.h>
+
+#include <igd_pwr.h>
+
+#include <general.h>
+#include <context.h>
+#include <mode.h>
+#include <utils.h>
+
+#include <plb/regs.h>
+
+#include "../cmn/i2c_dispatch.h"
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/*......................................................................... */
+extern igd_display_port_t dvob_port_plb;
+
+/*......................................................................... */
+static int i2c_read_regs_plb(
+	igd_context_t *context,
+	unsigned long i2c_bus,
+	unsigned long i2c_speed,
+	unsigned long dab,
+	unsigned char reg,
+	unsigned char FAR *buffer,
+	unsigned long num_bytes,
+	unsigned long flags);
+
+static int i2c_write_reg_list_plb(
+	igd_context_t *context,
+	unsigned long i2c_bus,
+	unsigned long i2c_speed,
+	unsigned long dab,
+	pd_reg_t *reg_list,
+	unsigned long flags);
+
+i2c_dispatch_t i2c_dispatch_plb = {
+	i2c_read_regs_plb,
+	i2c_write_reg_list_plb,
+};
+
+
+/*.......................................................................... */
+typedef enum {
+
+	GMBUS_SPEED_50K     = 0x0100,
+	GMBUS_SPEED_100K	= 0x0000,
+	GMBUS_SPEED_400K	= 0x0200,
+	GMBUS_SPEED_1000K	= 0x0300,
+
+} gmbus_speed_t;
+
+typedef enum {
+
+	SDVOB_ADDR	= 0x70,
+	SDVOC_ADDR	= 0x72,
+
+} sdvo_dev_addr_t;
+
+typedef enum {
+
+	DDC1_ADDR = 0xA0,
+	DDC2_ADDR = 0xA2,
+
+} gmbus_ddc_addr_t;
+
+
+typedef enum {
+
+	GMBUS_PINS_DEDICATED = 1, /* Dedicated Control/GMBUS Pins */
+	/* LCTRCLKA, LCTRLCLKB SSC Clock Device */
+	GMBUS_PINS_ANALOG	= 2,  /* Analog DDC */
+	GMBUS_PINS_INT_LVDS = 3,  /* Alviso : Integrated Digital Panel */
+	GMBUS_PINS_SDVO     = 5,  /* SDVO Registers, DDC, PROM */
+
+} gmbus_pins_pair_t;
+
+
+typedef enum {
+
+	I2C_WRITE = 0,
+	I2C_READ  = 1,
+
+} i2c_bus_dir_t;
+
+/*.......................................................................... */
+typedef enum {
+
+	SDVO_BUS_PROM = BIT(0),
+	SDVO_BUS_DDC1 = BIT(1),
+	SDVO_BUS_DDC2 = BIT(2),
+
+} sdvo_bus_switch_t;
+
+#define SDVO_OPCODE_BUS_SWITCH	0x7A
+
+#define SDVO_INDEX_PARAM_1		0x07
+#define SDVO_INDEX_OPCODE		0x08
+#define SDVO_INDEX_STATUS		0x09
+
+#define SDVO_STATUS_SUCCESS     0x01
+#define SDVO_STATUS_PENDING     0x04
+
+/*.......................................................................... */
+/*
+ * In 16-bit, the mmio is a 16-bit pointer, the watcom 1.2 compiler will have
+ * error if directly convert it to unsigned long.  Normally, have to cast it to
+ * unsigned short first then cast again to unsigned long; then, it will be
+ * correct.  But this type of casting may cause some error in the 32 and 64 bit
+ * code.  Since mmio will be equal to zero for 16-bit code.  Add the checking
+ * for MICRO definition code to correct the macro by remove mmio.
+ */
+#define READ_GMCH_REG(reg)			EMGD_READ32(EMGD_MMIO(mmio) + reg)
+#define WRITE_GMCH_REG(reg, data)	EMGD_WRITE32(data, EMGD_MMIO(mmio) + reg)
+
+static int gmbus_init(unsigned char *mmio, unsigned long i2c_bus,
+	unsigned long i2c_speed);
+
+static int gmbus_read_edid(unsigned char *mmio,
+	unsigned long ddc_addr,
+	unsigned long slave_addr,
+	unsigned long index,
+	unsigned long num_bytes,
+	unsigned char FAR *buffer);
+
+static int gmbus_read_reg(unsigned char *mmio,
+	unsigned long slave_addr,
+	unsigned long index,
+	unsigned char FAR *data);
+
+static int gmbus_write_reg(unsigned char *mmio,
+	unsigned long slave_addr,
+	unsigned long index,
+	unsigned char data);
+
+static int gmbus_set_control_bus_switch(unsigned char *mmio,
+	unsigned long slave_addr,
+	gmbus_ddc_addr_t ddc_addr);
+
+static int gmbus_wait_event_one(unsigned char *mmio, unsigned long bit);
+static int gmbus_wait_event_zero(unsigned char *mmio, unsigned long bit);
+static int gmbus_error_handler(unsigned char *mmio);
+
+/*!
+ * i2c_read_regs_plb is called to read Edid or a single sDVO register
+ *
+ * @param context
+ * @param i2c_bus port->ddc_reg, port->i2c_reg
+ * @param i2c_speed 50, 100, 400, 1000 (Khz)
+ * @param dab 0x70/0x72 (sDVO Regs), 0xA0/0xA2 (sDVO/Analog DDC)
+ * @param reg I2C Reg Index
+ * @param num_bytes <= 508
+ * @param buffer Data read
+ * @param flags unused, put in to match TNC func signature
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int i2c_read_regs_plb(igd_context_t *context,
+	unsigned long i2c_bus,
+	unsigned long i2c_speed,
+	unsigned long dab,
+	unsigned char reg,
+	unsigned char FAR *buffer,
+	unsigned long num_bytes,
+	unsigned long flags)
+{
+	unsigned char *mmio = EMGD_MMIO(context->device_context.virt_mmadr);
+	unsigned long slave_addr;
+
+	if (! gmbus_init(mmio, i2c_bus, i2c_speed)) {
+		EMGD_DEBUG("Error ! i2c_read_regs_plb : gmbus_init() failed");
+		return 1;
+	}
+
+	/*	If the request is to read Edid from sDVO display, find out the */
+	/*	i2c addres of the sDVO device */
+	if (i2c_bus == GMBUS_DVOB_DDC) {
+		slave_addr = dvob_port_plb.dab;
+
+	} else {
+		slave_addr = 0;
+
+	}
+
+	switch (i2c_bus) {
+	case GMBUS_ANALOG_DDC :
+	case GMBUS_INT_LVDS_DDC :
+	case GMBUS_DVOB_DDC :
+	case GMBUS_DVOC_DDC :
+		if (! gmbus_read_edid(mmio, dab, slave_addr, reg, num_bytes, buffer)) {
+
+			EMGD_DEBUG("Error ! i2c_read_regs_plb : gmbus_read_edid() failed");
+			return 1;
+		}
+		break;
+
+	case GMBUS_DVO_REG :
+		if (! gmbus_read_reg(mmio, dab, reg, buffer)) {
+
+			EMGD_DEBUG("Error ! i2c_read_regs_plb : gmbus_read_reg() failed");
+			return 1;
+		}
+		break;
+
+	default :
+		EMGD_ERROR("Error ! i2c_read_regs_plb : Invalid i2c_bus=0x%lx",
+			i2c_bus);
+		return 1;
+	}
+
+	return 0;
+}
+
+/*!
+ * i2c_write_reg_list_plb is called to write a list of i2c registers to sDVO
+ * device
+ *
+ * @param context
+ * @param i2c_bus NAP_GMBUS_DVOB_DDC/NAP_GMBUS_DVOC_DDC
+ * @param i2c_speed 1000 Khz
+ * @param dab 0x70/0x72
+ * @param reg_list List of i2c indexes and data, terminated with register index
+ *  set to PD_REG_LIST_END
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int i2c_write_reg_list_plb(igd_context_t *context,
+	unsigned long i2c_bus,
+	unsigned long i2c_speed,
+	unsigned long dab,
+	pd_reg_t *reg_list,
+	unsigned long flags)
+{
+	unsigned char *mmio = EMGD_MMIO(context->device_context.virt_mmadr);
+	unsigned long reg_num = 0, ddc_addr = 0, slave_addr = 0;
+
+	if (! gmbus_init(mmio, i2c_bus, i2c_speed)) {
+
+		EMGD_DEBUG("Error ! i2c_write_reg_list_plb : gmbus_init() failed");
+		return 1;
+	}
+	/*If it is SDVO Make sure we issue SDVO command to enable DDC access*/
+	if ((i2c_bus == GMBUS_DVOB_DDC) || (i2c_bus == GMBUS_DVOC_DDC)) {
+		if (i2c_bus == GMBUS_DVOB_DDC) {
+			slave_addr = dvob_port_plb.dab;
+		}else if (i2c_bus == GMBUS_DVOC_DDC) {
+			/* Is DVOC available in PLB? */
+			//slave_addr = dvoc_port_plb.dab;
+			slave_addr = 0;
+		}
+		ddc_addr = 0;
+		if (! gmbus_set_control_bus_switch(mmio, slave_addr, ddc_addr)) {
+			EMGD_DEBUG("Error ! i2c_write_reg_list_plb : gmbus_set_control_bus_switch()"
+					 " failed");
+			return 1;
+		}
+		while (reg_list[reg_num].reg != PD_REG_LIST_END) {
+
+			if (! gmbus_write_reg(mmio, dab, reg_list[reg_num].reg,
+					  (unsigned char)reg_list[reg_num].value)) {
+
+				EMGD_DEBUG("Error ! i2c_write_reg_list_plb : gmbus_write_reg() failed, reg_num=%lu",
+					reg_num);
+
+				return 1;
+			}
+		reg_num++;
+		}
+		/*...................................................................... */
+		/* Issue a Stop Command */
+		gmbus_wait_event_one(mmio, HW_WAIT);
+		WRITE_GMCH_REG(GMBUS1, STO | SW_RDY | ddc_addr);
+		gmbus_wait_event_one(mmio, HW_RDY);
+		gmbus_wait_event_zero(mmio, GA);
+		gmbus_error_handler(mmio);
+		WRITE_GMCH_REG(GMBUS1, SW_RDY);
+		WRITE_GMCH_REG(GMBUS1, SW_CLR_INT);
+		WRITE_GMCH_REG(GMBUS1, 0);
+		WRITE_GMCH_REG(GMBUS5, 0);
+		WRITE_GMCH_REG(GMBUS0, 0);
+		/*...................................................................... */
+		return 0;
+	}
+	while (reg_list[reg_num].reg != PD_REG_LIST_END) {
+
+		if (! gmbus_write_reg(mmio, dab, reg_list[reg_num].reg,
+				(unsigned char)reg_list[reg_num].value)) {
+
+			EMGD_DEBUG("Error ! i2c_write_reg_list_plb : gmbus_write_reg() failed, reg_num=%lu",
+				reg_num);
+
+			return 1;
+		}
+
+		reg_num++;
+	}
+
+	return 0;
+}
+
+/*!
+ * gmbus_init initializes the GMBUS controller with specified bus and speed
+ *
+ * @param mmio
+ * @param i2c_bus sDVO B/C Reg/DDC or Analog DDC
+ * @param i2c_speed 50/100/400/1000 Khz
+ *
+ * @return TRUE(1) on success
+ * @return FALSE(0) on failure
+ */
+static int gmbus_init(unsigned char *mmio, unsigned long i2c_bus,
+	unsigned long i2c_speed)
+{
+	gmbus_pins_pair_t pin_pair;
+	gmbus_speed_t bus_speed;
+
+	switch (i2c_bus) {
+
+	case GMBUS_DVO_REG :
+	case GMBUS_DVOB_DDC :
+	case GMBUS_DVOC_DDC :
+		pin_pair = GMBUS_PINS_SDVO;
+		break;
+
+	case GMBUS_ANALOG_DDC :
+		pin_pair = GMBUS_PINS_ANALOG;
+		break;
+
+	case GMBUS_INT_LVDS_DDC :
+		pin_pair = GMBUS_PINS_INT_LVDS;
+		break;
+
+	default :
+		EMGD_ERROR("Error ! gmbus_init : Invalid i2c_bus=0x%lx", i2c_bus);
+		return 0;
+	}
+
+	switch (i2c_speed) {
+
+	case 50 :		/* Slow speed */
+		bus_speed = GMBUS_SPEED_50K;
+		break;
+
+	case 400 :		/* SPD */
+		bus_speed = GMBUS_SPEED_400K;
+		break;
+
+	case 1000 :     /* sDVO Registers */
+		bus_speed = GMBUS_SPEED_1000K;
+		break;
+
+	case 100 :      /* DDC */
+	default :
+		bus_speed = GMBUS_SPEED_100K;
+		break;
+	}
+
+	WRITE_GMCH_REG(GMBUS5, 0);   /* Clear the word index reg */
+	WRITE_GMCH_REG(GMBUS0, pin_pair | bus_speed);
+
+	return 1;
+}
+
+/*!
+ * gmbus_wait_event_zero waits for specified GMBUS2 register bit to be deasserted
+ *
+ * @param mmio
+ * @param bit
+ *
+ * @return TRUE(1) on success. The bit was deasserted in the specified timeout period
+ * @return FALSE(0) on failure
+ */
+static int gmbus_wait_event_zero(unsigned char *mmio, unsigned long bit)
+{
+	unsigned long i;
+	unsigned long status;
+
+	for (i = 0; i < 0x1000; i++) {
+
+		status = READ_GMCH_REG(GMBUS2);
+
+		if ((status & bit) == 0) {
+
+			return 1;
+		}
+	}
+
+	EMGD_DEBUG("Error ! gmbus_wait_event_zero : Failed : bit=0x%lx, status=0x%lx, forcing reset",
+		bit, status);
+
+	/* If we are here, that means that the GBMUS is busy or in a bad
+	 * state, the situation was observed
+	 * that the GMBUS never becomes available (idle state) after S3.
+	 * This results in the driver never being able to set the display.
+	 *
+	 * To fix this, we force force a reset of the GMBUS.
+	 */
+	WRITE_GMCH_REG(GMBUS1, SW_RDY);
+	WRITE_GMCH_REG(GMBUS1, SW_CLR_INT);
+	WRITE_GMCH_REG(GMBUS1, 0);
+
+	return 1;
+}
+
+/*!
+ * gmbus_wait_event_one wait for specified GMBUS2 register bits to be asserted
+ *
+ * @param mmio
+ * @param bit
+ *
+ * @return TRUE(1) on success. The bit was asserted in the specified timeout period
+ * @return FALSE(0) on failure
+ */
+static int gmbus_wait_event_one(unsigned char *mmio, unsigned long bit)
+{
+	unsigned long i;
+	unsigned long status;
+
+	for (i = 0; i < 0x10000; i++) {
+
+		status = READ_GMCH_REG(GMBUS2);
+		if ((status & bit) != 0) {
+
+			return 1;
+		}
+	}
+
+	EMGD_DEBUG("Error ! gmbus_wait_event_one : Failed : bit=0x%lx, status=0x%lx",
+		bit, status);
+
+	return 0;
+}
+
+/*!
+ * gmbus_error_handler attempts to recover from timeout error
+ *
+ * @param mmio
+ *
+ * @return TRUE(1) error was detected and handled
+ * @return FALSE(0) there was no error
+ */
+static int gmbus_error_handler(unsigned char *mmio)
+{
+	unsigned long status = READ_GMCH_REG(GMBUS2);
+
+	/* Clear the SW_INT, wait for HWRDY and GMBus active (GA) */
+	if ((status & HW_BUS_ERR) || (status & HW_TMOUT)) {
+
+		EMGD_DEBUG("Error ! gmbus_error_handler : Resolving error=0x%lx",
+			status);
+
+		WRITE_GMCH_REG(GMBUS1, SW_RDY);
+		WRITE_GMCH_REG(GMBUS1, SW_CLR_INT);
+		WRITE_GMCH_REG(GMBUS1, 0);
+
+		gmbus_wait_event_zero(mmio, GA);
+
+		return 1;	/* Handled the error */
+	}
+
+	return 0;	/* There was no error */
+}
+
+/*!
+ * Assemble 32 bit GMBUS1 command
+ *
+ * @param slave_addr 0x70/0x72
+ * @param index 0 - 256
+ * @param num_bytes Bytes to transfer
+ * @param flags Bits 25-31 of GMBUS1
+ * @param i2c_dir I2C_READ / I2C_WRITE
+ *
+ * @return The assembled command
+ */
+static unsigned long gmbus_assemble_command(unsigned long slave_addr, unsigned long index,
+	unsigned long num_bytes, unsigned long flags,
+	i2c_bus_dir_t i2c_dir)
+{
+	unsigned long cmd = flags | ENIDX | ENT | (num_bytes << 16) | (index << 8) |
+						slave_addr | i2c_dir;
+
+	return cmd;
+}
+
+/*!
+ * gmbus_send_pkt transmits a block a data to specified i2c slave device
+ *
+ * @param mmio
+ * @param slave_addr I2C device address
+ * @param index Starting i2c register index
+ * @param pkt_size 1 - 508 bytes
+ * @param pkt Bytes to send
+ *
+ * @return TRUE(1) if successful in sending the specified number of bytes
+ * @return FALSE(0) on failure
+ */
+static int gmbus_send_pkt(unsigned char *mmio,
+	unsigned long slave_addr, unsigned long index,
+	unsigned long pkt_size, void *pkt)
+{
+	unsigned long gmbus1_cmd;
+	unsigned long bytes_sent;
+	unsigned long *data;
+
+	if ((pkt_size == 0) || (pkt == NULL) || (pkt_size > 508)) {
+
+		return 0;
+	}
+
+	data = (unsigned long *)pkt;
+
+	/*...................................................................... */
+	gmbus_error_handler(mmio);
+
+	gmbus1_cmd = gmbus_assemble_command(slave_addr, index, pkt_size,
+										STA, I2C_WRITE);
+	if (pkt_size <= 4) {
+
+		gmbus1_cmd |= SW_RDY;
+	}
+
+	/*...................................................................... */
+	bytes_sent = 0;
+
+	do {
+
+		WRITE_GMCH_REG(GMBUS3, *data);
+
+		if (bytes_sent == 0) {
+
+			WRITE_GMCH_REG(GMBUS1, gmbus1_cmd);
+		}
+
+		if (! gmbus_wait_event_one(mmio, HW_RDY)) {
+
+			EMGD_DEBUG("Error ! gmbus_send_pkt : Failed to get HW_RDY, bytes_sent=%ld",
+				bytes_sent);
+
+			return 0;
+		}
+
+		if (gmbus_error_handler(mmio)) {
+
+			EMGD_DEBUG("Error ! gmbus_send_pkt : gmbus error, bytes_sent=%ld",
+				bytes_sent);
+
+			return 0;
+		}
+
+		data++;
+
+		if (pkt_size >= 4) {
+			bytes_sent += 4;
+
+		} else {
+			bytes_sent += pkt_size;
+		}
+
+	} while (bytes_sent < pkt_size);
+
+	/*...................................................................... */
+	if (bytes_sent != pkt_size) {
+
+		return 0;
+
+	} else {
+
+		return 1;
+	}
+}
+
+/*!
+ * gmbus_recv_pkt reads a block of data from specified i2c slave device
+ *
+ * @param mmio
+ * @param slave_addr I2C device address
+ * @param index Starting i2c register index
+ * @param pkt_size 1 - 508 bytes
+ * @param pkt Bytes to send
+ *
+ * @return TRUE(1) if successful in receiving specified number of bytes
+ * @return FALSE(0) on failure
+ */
+static int gmbus_recv_pkt(unsigned char *mmio,
+	unsigned long slave_addr, unsigned long index,
+	unsigned long pkt_size, void FAR *pkt)
+{
+	unsigned long gmbus1_cmd;
+	unsigned long bytes_rcvd;
+	unsigned long FAR *data;
+
+	if ((pkt_size == 0) || (pkt == NULL) || (pkt_size > 508)) {
+
+		return 0;
+	}
+
+	data = (unsigned long FAR *)pkt;
+
+	/*...................................................................... */
+	gmbus_error_handler(mmio);
+
+	/* Program the command */
+	gmbus1_cmd = gmbus_assemble_command(slave_addr, index, pkt_size,
+										STA | SW_RDY, I2C_READ);
+	WRITE_GMCH_REG(GMBUS1, gmbus1_cmd);
+
+	/*...................................................................... */
+	bytes_rcvd = 0;
+	do {
+
+		unsigned long gmbus3_data;
+		unsigned long bytes_left = pkt_size - bytes_rcvd;
+
+		if (! gmbus_wait_event_one(mmio, HW_RDY)) {
+
+			EMGD_DEBUG("Error ! gmbus_recv_pkt : Failed to get HW_RDY, "
+				"bytes_rcvd=%ld", bytes_rcvd);
+			break;
+		}
+
+		if (gmbus_error_handler(mmio)) {
+
+			EMGD_DEBUG("Error ! gmbus_recv_pkt : gmbus error, bytes_rcvd=%ld",
+				bytes_rcvd);
+			break;
+		}
+
+		gmbus3_data = READ_GMCH_REG(GMBUS3);
+
+		switch (bytes_left) {
+
+		case 1 :
+			*(unsigned char *)data = (unsigned char)gmbus3_data;
+			break;
+
+		case 2 :
+			*(unsigned short *)data = (unsigned short)gmbus3_data;
+			break;
+
+		case 3 :
+		{
+			unsigned char *dest = (unsigned char *)data;
+			 unsigned char *src  = (unsigned char *)&(gmbus3_data);
+			dest[0] = src[0];
+			dest[1] = src[1];
+			dest[2] = src[2];
+
+			break;
+		}
+
+		default :	/* >= 4 */
+			*data = gmbus3_data;
+			break;
+		}
+
+		if (bytes_left > 4) {
+			bytes_rcvd += 4;
+			data++;
+
+		} else {
+			bytes_rcvd += bytes_left;
+
+		}
+
+	} while (bytes_rcvd < pkt_size);
+
+	/*...................................................................... */
+	if (bytes_rcvd < pkt_size) {
+		return 0;
+
+	} else {
+		return 1;
+	}
+}
+
+/*!
+ * gmbus_set_control_bus_switch sends sDVO command to switch i2c bus to read EDID
+ * or SPD data
+ *
+ * @param mmio
+ * @param slave_addr sDVO device address (0x70/0x72)
+ * @param ddc_addr DDC1_ADDR/DDC2_ADDR
+ *
+ * @return TRUE(1) if successful in sending the opcode
+ * @return FALSE(0) on failure
+ */
+static int gmbus_set_control_bus_switch(unsigned char *mmio,
+	unsigned long slave_addr,
+	gmbus_ddc_addr_t ddc_addr)
+{
+	unsigned char data;
+	sdvo_bus_switch_t bus_switch;
+	int retry;
+
+	bus_switch = SDVO_BUS_DDC1;
+
+	/*...................................................................... */
+	/*	Transmit the Arguments */
+	if (! gmbus_send_pkt(mmio, slave_addr, SDVO_INDEX_PARAM_1, 1, &bus_switch)) {
+
+		EMGD_DEBUG("Error ! gmbus_set_control_bus_switch : gmbus_send_pkt() failed");
+
+		return 0;
+	}
+
+	/*...................................................................... */
+	/* Generate I2C stop cycle */
+	gmbus_wait_event_one(mmio, HW_WAIT);
+	WRITE_GMCH_REG(GMBUS1, STO | SW_RDY | slave_addr);
+	gmbus_wait_event_one(mmio, HW_RDY);
+	gmbus_wait_event_zero(mmio, GA);
+
+	/*...................................................................... */
+	/* Transmit the Opcode */
+	data = SDVO_OPCODE_BUS_SWITCH;
+	if (! gmbus_send_pkt(mmio, slave_addr, SDVO_INDEX_OPCODE, 1, &data)) {
+
+		EMGD_DEBUG("Error ! gmbus_set_control_bus_switch : gmbus_send_pkt(Opcode)"
+				 " failed");
+
+		return 0;
+	}
+
+	/*...................................................................... */
+	/* Read Status */
+	for (retry = 0; retry < 3; retry++) {
+		if (! gmbus_recv_pkt(mmio, slave_addr, SDVO_INDEX_STATUS, 1, &data)) {
+
+			continue;
+		}
+
+		if (data != SDVO_STATUS_PENDING) {
+
+			break;
+		}
+	}
+
+	/*...................................................................... */
+	/* Send Stop */
+	gmbus_wait_event_one(mmio, HW_WAIT);
+	WRITE_GMCH_REG(GMBUS1, STO | SW_RDY | slave_addr);
+	gmbus_wait_event_one(mmio, HW_RDY);
+	gmbus_wait_event_zero(mmio, GA);
+
+	/*...................................................................... */
+	if (data != SDVO_STATUS_SUCCESS) {
+
+		EMGD_DEBUG("Error ! gmbus_set_control_bus_switch : Opcode Bus Switch failed");
+
+		return 0;
+	}
+
+	return 1;
+}
+
+/*!
+ * gmbus_read_edid reads specified number of Edid data bytes
+ *
+ * @param mmio
+ * @param ddc_addr 0xA0/0xA2 (DDC1/DDC2)
+ * @param slave_addr 0x70/0x72 (sDVOB, sDVOC), 0 Analog
+ * @param index i2c register index
+ * @param num_bytes <= 508
+ * @param buffer Edid data read from the display
+ *
+ * @return TRUE(1) if successful in reading Edid
+ * @return FALSE(0) on failure
+ */
+static int gmbus_read_edid(unsigned char *mmio,
+	unsigned long ddc_addr,
+	unsigned long slave_addr,
+	unsigned long index,
+	unsigned long num_bytes,
+	unsigned char FAR *buffer)
+{
+	int status;
+
+	if ((slave_addr == SDVOB_ADDR) || (slave_addr == SDVOC_ADDR)) {
+
+		if (! gmbus_set_control_bus_switch(mmio, slave_addr, ddc_addr)) {
+
+			EMGD_DEBUG("Error ! gmbus_read_edid : gmbus_set_control_bus_switch()"
+					 " failed");
+
+			return 0;
+		}
+	} else {
+		/*	Reset the bus */
+		gmbus_recv_pkt(mmio, ddc_addr, 0, 1, buffer);
+	}
+
+	status = gmbus_recv_pkt(mmio, ddc_addr, index, num_bytes, buffer);
+	if (! status) {
+
+		EMGD_DEBUG("Error ! gmbus_read_edid : gmbus_recv_pkt() failed");
+	}
+
+	/*...................................................................... */
+	/* Issue a Stop Command */
+
+	gmbus_wait_event_one(mmio, HW_WAIT);
+	WRITE_GMCH_REG(GMBUS1, STO | SW_RDY | ddc_addr);
+	gmbus_wait_event_one(mmio, HW_RDY);
+
+	gmbus_wait_event_zero(mmio, GA);
+
+	gmbus_error_handler(mmio);
+	WRITE_GMCH_REG(GMBUS1, SW_RDY);
+	WRITE_GMCH_REG(GMBUS1, SW_CLR_INT);
+	WRITE_GMCH_REG(GMBUS1, 0);
+	WRITE_GMCH_REG(GMBUS5, 0);
+	WRITE_GMCH_REG(GMBUS0, 0);
+
+	/*...................................................................... */
+	return status;
+}
+
+/*!
+ * gmbus_read_reg reads one i2c register
+ *
+ * @param mmio
+ * @param slave_addr 0x70/0x72 (sDVOB, sDVOC)
+ * @param index i2c register index
+ * @param data register data
+ *
+ * @return TRUE(1) if successful in reading the i2c register
+ * @return FALSE(0) on failure
+ */
+static int gmbus_read_reg(unsigned char *mmio,
+	unsigned long slave_addr,
+	unsigned long index,
+	unsigned char FAR *data)
+{
+	unsigned long gmbus1_cmd;
+
+	WRITE_GMCH_REG(GMBUS5, 0x0);		/* Clear Word Index register */
+
+	if (! gmbus_wait_event_zero(mmio, GA)) {
+
+		EMGD_DEBUG("Error ! gmbus_read_reg : Failed to get GA(1)");
+
+		return 0;
+	}
+
+	gmbus1_cmd = gmbus_assemble_command(slave_addr, index, 1,
+										STO | STA, I2C_READ);
+	WRITE_GMCH_REG(GMBUS1, gmbus1_cmd);
+
+	if (! gmbus_wait_event_zero(mmio, GA)) {
+
+		EMGD_DEBUG("Error ! gmbus_read_reg : Failed to get GA(2)");
+
+		return 0;
+	}
+
+	*data = (unsigned char)READ_GMCH_REG(GMBUS3);
+
+	return 1;
+}
+
+/*!
+ * gmbus_write_reg writes one i2c register
+ *
+ * @param mmio
+ * @param slave_addr 0x70/0x72 (sDVOB, sDVOC)
+ * @param index i2c register index
+ * @param data register data
+ *
+ * @return TRUE(1) if successful in updating the i2c register
+ * @return FALSE(0) if failed to update the register
+ */
+static int gmbus_write_reg(unsigned char *mmio,
+	unsigned long slave_addr,
+	unsigned long index,
+	unsigned char data)
+{
+	unsigned long gmbus1_cmd;
+
+	WRITE_GMCH_REG(GMBUS5, 0x0);		/* Clear Word Index register */
+
+	if (! gmbus_wait_event_zero(mmio, GA)) {
+
+		EMGD_DEBUG("Error ! gmbus_write_reg : Failed to get GA(1)");
+
+		return 0;
+	}
+
+	WRITE_GMCH_REG(GMBUS3, data);
+
+	gmbus1_cmd = gmbus_assemble_command(slave_addr, index, 1,
+										STO | STA, I2C_WRITE);
+	WRITE_GMCH_REG(GMBUS1, gmbus1_cmd);
+
+	if (! gmbus_wait_event_zero(mmio, GA)) {
+
+		EMGD_DEBUG("Error ! gmbus_write_reg : Failed to get GA(2)");
+		return 0;
+	}
+
+	return 1;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/tnc/i2c_bitbash_tnc.c b/drivers/gpu/drm/emgd/emgd/display/pi/tnc/i2c_bitbash_tnc.c
new file mode 100644
index 0000000..427aa29
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/tnc/i2c_bitbash_tnc.c
@@ -0,0 +1,599 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: i2c_bitbash_tnc.c
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Bitbash to read GPIO pins are done on LPC device 0:31:0. So do not
+ *  use EMGD_READ32 and EMGD_WRITE32 macros for read/write to device 31. These
+ *  macros do mmio only on device2.
+ *  To properly read/write mmio on device 31, use
+ *  READ_MMIO_REG_TNC(port_type, reg) and
+ *  WRITE_MMIO_REG_TNC(port_type, reg, data).
+ *  These macros properly set to work for all OSes including VBIOS, but
+ *  generate more code compared to EMGD_READ32 and EMGD_WRITE32. So use as
+ *  necessary.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.dpd
+
+#include <io.h>
+#include <memory.h>
+#include <sched.h>
+
+#include <igd_pwr.h>
+
+#include <general.h>
+#include <context.h>
+#include <mode.h>
+#include <utils.h>
+
+#include <tnc/regs.h>
+
+#include <intelpci.h>
+
+#include "../cmn/i2c_dispatch.h"
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+static int i2c_error_recovery_tnc(
+	unsigned long hold_time);
+
+static int i2c_write_byte_tnc(
+	unsigned char value,
+	unsigned long hold_time);
+
+static int i2c_read_byte_tnc(
+	unsigned char *value,
+	unsigned char ack,
+	unsigned long hold_time);
+
+int i2c_read_regs_gpio(
+	igd_context_t *context,
+	unsigned long i2c_bus,
+	unsigned long i2c_speed,
+	unsigned long dab,
+	unsigned char reg,
+	unsigned char FAR *buffer,
+	unsigned long num_bytes,
+	unsigned long flags);
+
+int i2c_write_reg_list_gpio(
+	igd_context_t *context,
+	unsigned long i2c_bus,
+	unsigned long i2c_speed,
+	unsigned long dab,
+	pd_reg_t *reg_list,
+	unsigned long flags);
+
+/* The LVDS GPIO clock lines are GPIOSUS[3]
+ * The LVDS GPIO data lines are GPIOSUS[4]
+ */
+#define GPIO_CLOCK	0x08
+#define GPIO_DATA	0x10
+
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+#if 0
+static void enable_gpio_tnc(igd_context_t *context)
+{
+	/*
+	 * NOTE: This really should be a system BIOS job.
+	 * The driver would not touch these register anymore since
+	 * it would cause the 13x7 panel fail to start.
+	 */
+
+	/* Enabling LVDS Data and LVDS Clock */
+	unsigned long temp;
+
+	temp = READ_MMIO_REG_TNC(IGD_PORT_LPC, RGEN);
+	temp |= (GPIO_DATA | GPIO_CLOCK);
+	WRITE_MMIO_REG_TNC(IGD_PORT_LPC, RGEN, temp);
+
+	return;
+}
+#endif
+
+/*!
+ *
+ * @param clock
+ * @param data
+ *
+ * @return void
+ */
+static void i2c_get(unsigned long *clock,
+	unsigned long *data)
+{
+	unsigned long temp;
+	/* Set Data as Input */
+	temp = READ_MMIO_REG_TNC(IGD_PORT_LPC, RGIO);
+	temp |= (GPIO_DATA);
+	WRITE_MMIO_REG_TNC(IGD_PORT_LPC, RGIO, temp);
+	/* Read Data */
+	*data = (READ_MMIO_REG_TNC(IGD_PORT_LPC, RGLVL) & GPIO_DATA) ? 1:0;
+	*clock = (READ_MMIO_REG_TNC(IGD_PORT_LPC, RGLVL) & GPIO_CLOCK) ? 1:0;
+
+#if 0
+	EMGD_WRITE32(0, EMGD_MMIO(mmio) + i2c_bus);
+	c = EMGD_READ32(EMGD_MMIO(mmio) + i2c_bus)>>4;
+	*data = (c>>8) & 1;
+	*clock &= 1;
+#endif
+}
+
+/*!
+ *
+ * @param data
+ * @param hold_time
+ *
+ * @return void
+ */
+static void i2c_set_data(int data,
+	unsigned long hold_time)
+{
+	unsigned long temp;
+	/* The LVDS GPIO data lines are GPIOSUS[4] */
+	/* Set as Output */
+	temp = READ_MMIO_REG_TNC(IGD_PORT_LPC, RGIO);
+	temp &= ~GPIO_DATA;
+	WRITE_MMIO_REG_TNC(IGD_PORT_LPC, RGIO, temp);
+	/* Read status register */
+	temp = READ_MMIO_REG_TNC(IGD_PORT_LPC, RGLVL);
+
+	if(data){
+		/* Set level to High */
+		temp |= GPIO_DATA;
+	} else {
+		/* Set level to low */
+		temp &= ~GPIO_DATA;
+	}
+	WRITE_MMIO_REG_TNC(IGD_PORT_LPC, RGLVL, temp);
+
+	OS_DELAY(hold_time);
+
+#if 0
+	/* Implementation using Display GPIO
+	 * For alm, the default data value "could" be 0
+	 */
+	/*
+	 * Simplified definition for the bits
+	 * 11: GPIO data Value
+	 * 10: GPIO Data Mask
+	 * 9: GPIO Data Direction Value
+	 * 8: GPIO Data Direction Mask
+	 */
+	EMGD_WRITE32(data ? 0x500 : 0x700, EMGD_MMIO(mmio) + i2c_bus);
+	EMGD_WRITE32(data ? 0x400 : 0x600, EMGD_MMIO(mmio) + i2c_bus);
+	OS_DELAY(hold_time);
+#endif
+}
+
+/*!
+ *
+ * @param clock
+ * @param hold_time
+ *
+ * @return void
+ */
+static void i2c_set_clock(int clock,
+	unsigned long hold_time)
+{
+	unsigned long temp;
+	/* The LVDS GPIO clock lines are GPIOSUS[3] */
+	/* Set as Output */
+	temp = READ_MMIO_REG_TNC(IGD_PORT_LPC, RGIO);
+	temp &= ~GPIO_CLOCK;
+	WRITE_MMIO_REG_TNC(IGD_PORT_LPC, RGIO, temp);
+	/* Read Status Register */
+	temp = READ_MMIO_REG_TNC(IGD_PORT_LPC, RGLVL);
+
+	if(clock){
+		/* Set level to High */
+		temp |= GPIO_CLOCK;
+
+	} else {
+		/* Set level to low */
+		temp &= ~GPIO_CLOCK;
+	}
+	WRITE_MMIO_REG_TNC(IGD_PORT_LPC, RGLVL, temp);
+
+	OS_DELAY(hold_time);
+
+#if 0
+	/*
+	 * Simplified definition for the bits
+	 * 3: GPIO Clock Value
+	 * 2: GPIO Clock Mask
+	 * 1: GPIO Clock Direction Value
+	 * 0: GPIO Clock Direction Mask
+	 */
+
+	EMGD_WRITE32(clock ? 0x5 : 0x7, EMGD_MMIO(mmio) + i2c_bus);
+	EMGD_WRITE32(clock ? 0x4 : 0x6, EMGD_MMIO(mmio) + i2c_bus);
+	OS_DELAY(hold_time);
+#endif
+}
+
+/*!
+ *
+ * @param hold_time
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int i2c_start_tnc(unsigned long hold_time)
+{
+	unsigned long sc, sd;
+
+	/* set sd high */
+	i2c_set_data(1, hold_time);
+
+	/* set clock high */
+	i2c_set_clock(1, hold_time);
+
+	/* Start condition happens when sd goes high to low when sc is high */
+	i2c_get(&sc, &sd);
+
+	if( 0 == sc ) {
+		// Data must be high
+		i2c_error_recovery_tnc(hold_time);
+		return 1;
+	}
+
+	i2c_set_data(0, hold_time);
+	i2c_set_clock(0, hold_time);
+
+	return 0;
+} /* end i2c_start */
+
+/*!
+ *
+ * @param hold_time
+ *
+ * @return 0
+ */
+static int i2c_stop_tnc(unsigned long hold_time)
+{
+	/* Stop condition happens when sd goes low to high when sc is high */
+	unsigned long sc,sd;
+
+	i2c_set_clock(0, hold_time);
+	i2c_set_data(0, hold_time);
+
+	i2c_set_clock(1, hold_time);
+
+	i2c_get(&sc, &sd);
+	/* Try another time */
+	if (sc == 0) {
+		i2c_set_clock(1, hold_time);
+	}
+	i2c_set_data(1, hold_time);
+
+	return 0;
+} /* end i2c_stop */
+
+/*!
+ *
+ * @param hold_time
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int i2c_error_recovery_tnc(unsigned long hold_time)
+{
+	unsigned char max_retries = 9;
+	unsigned long sc, sd;
+
+	while (max_retries--) {
+		i2c_get(&sc, &sd);
+		if (sd == 1 && sc == 1) {
+			return 0;
+		} else {
+			i2c_stop_tnc(hold_time);
+		}
+	}
+	EMGD_ERROR("Cannot recover I2C error.");
+
+	return 1;
+}
+
+/*!
+ *
+ * @param value
+ * @param hold_time
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int i2c_write_byte_tnc(unsigned char value,
+	unsigned long hold_time)
+{
+	int i;
+	unsigned long sc,sd;
+
+	/* I2C_DEBUG("i2c_write_byte"); */
+	for(i=7; i>=0; i--) {
+		i2c_set_clock(0, hold_time);
+		i2c_set_data(value>>i & 1, hold_time);
+
+		i2c_set_clock(1, hold_time);
+	}
+
+	/* Get ACK */
+	i2c_set_clock(0, hold_time);
+	/* Set data low. Possible inteference in some lvds panel */
+	i2c_set_data(0, hold_time);
+	i2c_set_clock(1, hold_time);
+	OS_DELAY(hold_time);
+
+	i2c_get(&sc, &sd);
+
+	i2c_set_clock(0, hold_time);
+
+	if (sd != 0) {
+		EMGD_ERROR("No ACK for byte 0x%x", value);
+		i2c_error_recovery_tnc(hold_time);
+		return 1;
+	}
+
+	return 0;
+
+} /* end i2c_write_byte */
+
+/*!
+ *
+ * @param value
+ * @param ack
+ * @param hold_time
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int i2c_read_byte_tnc(unsigned char *value,
+	unsigned char ack,
+	unsigned long hold_time)
+{
+	int i;
+	unsigned long sc, sd, temp;
+
+	*value = 0;
+	for(i=7; i>=0; i--) {
+		i2c_set_clock(1, hold_time);
+		i2c_get(&sc, &sd);
+		OS_DELAY(hold_time);
+		if(!sc) {
+			EMGD_DEBUG("Clock low on read %d", i);
+			i2c_error_recovery_tnc(hold_time);
+			return 1;
+		}
+		*value |= (sd & 1)<<i;
+		i2c_set_clock(0, hold_time);
+	}
+
+	if (ack) {
+		i2c_set_data(0, hold_time);
+	}
+
+	/* Master does not ACK */
+	i2c_set_clock(1, hold_time);
+	i2c_set_clock(0, hold_time);
+
+	if (ack) {
+		/* Set data as input as we continue to read */
+		temp = READ_MMIO_REG_TNC(IGD_PORT_LPC, RGIO);
+		temp |= GPIO_DATA;
+		WRITE_MMIO_REG_TNC(IGD_PORT_LPC, RGIO, temp);
+	}
+
+	return 0;
+} /* end i2c_read_byte */
+
+/*!
+ *
+ * @param context
+ * @param i2c_bus
+ * @param i2c_speed
+ * @param dab
+ * @param reg
+ * @param buffer
+ * @param num_bytes
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int i2c_read_regs_gpio(igd_context_t *context,
+	unsigned long i2c_bus,
+	unsigned long i2c_speed,
+	unsigned long dab,
+	unsigned char reg,
+	unsigned char FAR *buffer,
+	unsigned long num_bytes,
+	unsigned long flags	
+	)
+{
+	unsigned long hold_time;
+	unsigned char temp;
+	int i;
+	if (!i2c_speed) {
+		EMGD_DEBUG("i2c Speed failed.");
+		return 1;
+	}
+
+	/*
+	 * We are holding the clock LOW for "hold_time" and then HIGH for
+	 * "hold_time". Therefore, we double the clock speed in this calculation.
+	 */
+	if (flags & IGD_I2C_WRITE_FW){
+		hold_time = 1;
+	} else {
+	hold_time = 1000/(i2c_speed * 2);
+	}
+
+	/* enable_gpio_tnc(context); */
+
+	if (i2c_start_tnc(hold_time)) {
+		EMGD_DEBUG("i2c Start failed.");
+		return 1;
+	}
+
+	if (i2c_write_byte_tnc((unsigned char)dab & 0xFE,
+			hold_time)) {
+		EMGD_DEBUG("i2c DAB(W) failed.");
+		return 1;
+	}
+
+	if (i2c_write_byte_tnc(reg, hold_time)) {
+		EMGD_DEBUG("RAB failed.");
+		return 1;
+	}
+
+	if (i2c_start_tnc(hold_time)) {
+		EMGD_DEBUG("i2c ReStart failed");
+		return 1;
+	}
+
+	if (i2c_write_byte_tnc((unsigned char)dab | 0x01,
+			hold_time)) {
+		EMGD_ERROR("i2c DAB(R) failed");
+		return 1;
+	}
+
+
+	/* Read the requested number of bytes */
+	for(i=0; i<(int)(num_bytes-1); i++) {
+		/*
+		 * Use a local temp so that the FAR pointer doesn't have to
+		 * get passed down.
+		 */
+		if (i2c_read_byte_tnc(&temp, 1, hold_time)) {
+			EMGD_DEBUG("Read data byte %d failed", i);
+			EMGD_DEBUG("Exit i2c_read_regs_tnc with error");
+			return 1;
+		}
+		buffer[i] = temp;
+	}
+
+	/* No ACK on the last read */
+	if(i2c_read_byte_tnc(&temp, 0, hold_time)) {
+		EMGD_DEBUG("Read Data %d Failed", i);
+		EMGD_DEBUG("Exit i2c_read_regs_tnc with error");
+		return 1;
+	}
+	buffer[i] = temp;
+
+	i2c_stop_tnc(hold_time);
+	i2c_stop_tnc(hold_time);
+
+	return 0;
+}
+
+/*!
+ *
+ * @param context
+ * @param i2c_bus
+ * @param i2c_speed
+ * @param dab
+ * @param reg_list
+ * @param flags
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+int i2c_write_reg_list_gpio(igd_context_t *context,
+	unsigned long i2c_bus,
+	unsigned long i2c_speed,
+	unsigned long dab,
+	pd_reg_t *reg_list,
+	unsigned long flags)
+{
+	unsigned long hold_time;
+
+	if (!i2c_speed) {
+		return 1;
+	}
+
+	/*
+	 * We are holding the clock LOW for "hold_time" and then HIGH for
+	 * "hold_time". Therefore, we double the clock speed in this calculation.
+	 */
+	if (flags & IGD_I2C_WRITE_FW){
+		hold_time = 1;	
+	} else {
+	hold_time = 1000/(i2c_speed * 2);
+	}
+
+	/* enable_gpio_tnc(context); */
+
+	while(reg_list->reg != PD_REG_LIST_END) {
+		if (i2c_start_tnc(hold_time)) {
+			EMGD_DEBUG("Start failed");
+			return 1;
+		}
+
+		if (i2c_write_byte_tnc((unsigned char)dab & 0xFE,
+				hold_time)) {
+			EMGD_DEBUG("DAB(W) failed");
+			return 1;
+		}
+
+		/* Register Address */
+		if (i2c_write_byte_tnc((unsigned char)reg_list->reg, hold_time)) {
+			EMGD_DEBUG("RAB failed");
+			return 1;
+		}
+
+		do {
+			/*  New Value */
+			if (i2c_write_byte_tnc((unsigned char)reg_list->value, hold_time)) {
+				EMGD_DEBUG("Data failed");
+				return 1;
+			}
+
+			if(reg_list[1].reg != (reg_list[0].reg + 1)) {
+				reg_list++;
+				break;
+			}
+
+			EMGD_DEBUG("I2C Multi-Write Reg[%x] = 0x%x",
+				(unsigned short)reg_list->reg,
+				(unsigned short)reg_list->value);
+			reg_list++;
+		} while(flags & IGD_I2C_SERIAL_WRITE);
+
+
+		i2c_stop_tnc(hold_time);
+		i2c_stop_tnc(hold_time);
+	}
+
+	return 0;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/display/pi/tnc/i2c_gmbus_tnc.c b/drivers/gpu/drm/emgd/emgd/display/pi/tnc/i2c_gmbus_tnc.c
new file mode 100644
index 0000000..ed8cbb9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/display/pi/tnc/i2c_gmbus_tnc.c
@@ -0,0 +1,929 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: i2c_gmbus_tnc.c
+ * $Revision: 1.15 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.dpd
+
+#include <io.h>
+#include <memory.h>
+#include <sched.h>
+
+#include <igd_pwr.h>
+
+#include <general.h>
+#include <context.h>
+#include <mode.h>
+#include <utils.h>
+
+#include <tnc/regs.h>
+
+#include "../cmn/i2c_dispatch.h"
+
+/*!
+ * @addtogroup display_group
+ * @{
+ */
+
+/*......................................................................... */
+extern igd_display_port_t dvob_port_tnc;
+
+/*......................................................................... */
+static int i2c_read_regs_tnc(
+	igd_context_t *context,
+	unsigned long i2c_bus,
+	unsigned long i2c_speed,
+	unsigned long dab,
+	unsigned char reg,
+	unsigned char FAR *buffer,
+	unsigned long num_bytes,
+	unsigned long flags);
+
+static int i2c_write_reg_list_tnc(
+	igd_context_t *context,
+	unsigned long i2c_bus,
+	unsigned long i2c_speed,
+	unsigned long dab,
+	pd_reg_t *reg_list,
+	unsigned long flags);
+
+i2c_dispatch_t i2c_dispatch_tnc = {
+	i2c_read_regs_tnc,
+	i2c_write_reg_list_tnc,
+};
+
+
+/*.......................................................................... */
+typedef enum {
+
+	GMBUS_SPEED_50K     = 0x0100,
+	GMBUS_SPEED_100K	= 0x0000,
+	GMBUS_SPEED_400K	= 0x0200,
+	GMBUS_SPEED_1000K	= 0x0300,
+
+} gmbus_speed_t;
+
+typedef enum {
+
+	SDVOB_ADDR	= 0x70,
+
+} sdvo_dev_addr_t;
+
+typedef enum {
+
+	DDC1_ADDR = 0xA0,
+	DDC2_ADDR = 0xA2,
+
+} gmbus_ddc_addr_t;
+
+
+typedef enum {
+
+	GMBUS_PINS_DEDICATED = 1, /* Dedicated Control/GMBUS Pins */
+	GMBUS_PINS_SDVO     = 5,  /* SDVO Registers, DDC, PROM */
+
+} gmbus_pins_pair_t;
+
+
+typedef enum {
+
+	I2C_WRITE = 0,
+	I2C_READ  = 1,
+
+} i2c_bus_dir_t;
+
+/*.......................................................................... */
+typedef enum {
+
+	SDVO_BUS_PROM = BIT(0),
+	SDVO_BUS_DDC1 = BIT(1),
+	SDVO_BUS_DDC2 = BIT(2),
+
+} sdvo_bus_switch_t;
+
+#define SDVO_OPCODE_BUS_SWITCH	0x7A
+
+#define SDVO_INDEX_PARAM_1		0x07
+#define SDVO_INDEX_OPCODE		0x08
+#define SDVO_INDEX_STATUS		0x09
+
+#define SDVO_STATUS_SUCCESS     0x01
+#define SDVO_STATUS_PENDING     0x04
+
+/*.......................................................................... */
+/*
+ * In 16-bit, the mmio is a 16-bit pointer, the watcom 1.2 compiler will have
+ * error if directly convert it to unsigned long.  Normally, have to cast it to
+ * unsigned short first then cast again to unsigned long; then, it will be
+ * correct.  But this type of casting may cause some error in the 32 and 64 bit
+ * code.  Since mmio will be equal to zero for 16-bit code.  Add the checking
+ * for MICRO definition code to correct the macro by remove mmio.
+ */
+#define READ_GMCH_REG(reg)        READ_MMIO_REG_TNC(IGD_PORT_SDVO, reg)
+#define WRITE_GMCH_REG(reg, data) WRITE_MMIO_REG_TNC(IGD_PORT_SDVO, reg, data)
+
+static int gmbus_init(unsigned long i2c_bus,
+	unsigned long i2c_speed);
+
+static int gmbus_read_edid(unsigned long ddc_addr,
+	unsigned long slave_addr,
+	unsigned long index,
+	unsigned long num_bytes,
+	unsigned char FAR *buffer);
+
+static int gmbus_read_reg(unsigned long slave_addr,
+	unsigned long index,
+	unsigned char FAR *data);
+
+static int gmbus_write_reg(unsigned long slave_addr,
+	unsigned long index,
+	unsigned char data);
+
+static int gmbus_set_control_bus_switch(unsigned long slave_addr,
+	gmbus_ddc_addr_t ddc_addr);
+
+static int gmbus_wait_event_one(unsigned long bit);
+static int gmbus_wait_event_zero(unsigned long bit);
+static int gmbus_error_handler(void);
+
+/*.......................................................................... */
+extern int i2c_read_regs_gpio(
+	igd_context_t *context,
+	unsigned long i2c_bus,
+	unsigned long i2c_speed,
+	unsigned long dab,
+	unsigned char reg,
+	unsigned char FAR *buffer,
+	unsigned long num_bytes,
+	unsigned long flags);
+
+extern int i2c_write_reg_list_gpio(
+	igd_context_t *context,
+	unsigned long i2c_bus,
+	unsigned long i2c_speed,
+	unsigned long dab,
+	pd_reg_t *reg_list,
+	unsigned long flags);
+
+
+/*!
+ * i2c_read_regs_tnc is called to read Edid or a single sDVO register
+ *
+ * @param context
+ * @param i2c_bus port->ddc_reg, port->i2c_reg
+ * @param i2c_speed 50, 100, 400, 1000 (Khz)
+ * @param dab 0x70/0x72 (sDVO Regs), 0xA0/0xA2 (sDVO/Analog DDC)
+ * @param reg I2C Reg Index
+ * @param num_bytes <= 508
+ * @param buffer Data read
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int i2c_read_regs_tnc(igd_context_t *context,
+	unsigned long i2c_bus,
+	unsigned long i2c_speed,
+	unsigned long dab,
+	unsigned char reg,
+	unsigned char FAR *buffer,
+	unsigned long num_bytes,
+	unsigned long flags)
+{
+	unsigned long slave_addr = 0;
+
+	if(i2c_bus == I2C_INT_LVDS_DDC){
+		/*
+		 * Atom E6xx LVDS does not have GMBUS support. To read DDC register, we bit bash.
+		 * The i2c_speed is necessary to calculate the hold time. But i2c_bus is not needed.
+		 */
+
+		EMGD_DEBUG("i2c_read_regs_tnc : Using GPIO to read DDC");
+		return i2c_read_regs_gpio(context, i2c_bus, i2c_speed,	dab, reg, buffer, num_bytes, flags);
+
+	} else {
+
+		if (! gmbus_init(i2c_bus, i2c_speed)) {
+			EMGD_DEBUG("Error ! i2c_read_regs_tnc : gmbus_init() failed");
+			return 1;
+		}
+
+		/*	If the request is to read Edid from sDVO display, find out the */
+		/*	i2c addres of the sDVO device */
+		if (i2c_bus == GMBUS_DVOB_DDC) {
+			slave_addr = dvob_port_tnc.dab;
+		}
+
+		switch (i2c_bus) {
+		case GMBUS_DVOB_DDC :
+			if (! gmbus_read_edid(dab, slave_addr, reg, num_bytes, buffer)) {
+
+				EMGD_DEBUG("Error ! i2c_read_regs_tnc : gmbus_read_edid() failed");
+				return 1;
+			}
+			break;
+
+		case GMBUS_DVO_REG :
+			if (! gmbus_read_reg(dab, reg, buffer)) {
+
+				EMGD_DEBUG("Error ! i2c_read_regs_tnc : gmbus_read_reg() failed");
+				return 1;
+			}
+			break;
+
+		default :
+			EMGD_ERROR("Error ! i2c_read_regs_tnc : Invalid i2c_bus=0x%lx",
+				i2c_bus);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/*!
+ * i2c_write_reg_list_tnc is called to write a list of i2c registers to sDVO
+ * device
+ *
+ * @param context
+ * @param i2c_bus NAP_GMBUS_DVOB_DDC/NAP_GMBUS_DVOC_DDC
+ * @param i2c_speed 1000 Khz
+ * @param dab 0x70/0x72
+ * @param reg_list List of i2c indexes and data, terminated with register index
+ *  set to PD_REG_LIST_END
+ *
+ * @return 0 on success
+ * @return 1 on failure
+ */
+static int i2c_write_reg_list_tnc(igd_context_t *context,
+	unsigned long i2c_bus,
+	unsigned long i2c_speed,
+	unsigned long dab,
+	pd_reg_t *reg_list,
+	unsigned long flags)
+{
+	unsigned long reg_num = 0, ddc_addr = 0, slave_addr = 0;
+
+	if(i2c_bus == I2C_INT_LVDS_DDC){
+		/* There are no GMBUS pins for internal LVDS on Atom E6xx.
+		 * Forcing us to use bit bashing */
+		/* FIXME: determine which GPIO pin is used for bit bashing
+		 *		i2c_bus is not defined
+		 */
+		EMGD_DEBUG("i2c_write_reg_list_tnc : Using GPIO to write DDC");
+		return i2c_write_reg_list_gpio(context, i2c_bus, i2c_speed, dab, reg_list, flags);
+
+	} else {
+
+		if (! gmbus_init(i2c_bus, i2c_speed)) {
+
+			EMGD_DEBUG("Error ! i2c_write_reg_list_tnc : gmbus_init() failed");
+			return 1;
+		}
+		/*If it is SDVO Make sure we issue SDVO command to enable DDC access*/
+		if (i2c_bus == GMBUS_DVOB_DDC) {
+			slave_addr = dvob_port_tnc.dab;
+			ddc_addr = 0;
+
+			if (! gmbus_set_control_bus_switch(slave_addr, ddc_addr)) {
+				EMGD_DEBUG("Error ! i2c_write_reg_list_tnc : gmbus_set_control_bus_switch()"
+						 " failed");
+				return 1;
+			}
+			while (reg_list[reg_num].reg != PD_REG_LIST_END) {
+
+				if (! gmbus_write_reg(dab, reg_list[reg_num].reg,
+						  (unsigned char)reg_list[reg_num].value)) {
+
+					EMGD_DEBUG("Error ! i2c_write_reg_list_tnc : gmbus_write_reg() failed, reg_num=%lu",
+						reg_num);
+
+					return 1;
+				}
+			reg_num++;
+			}
+			/*...................................................................... */
+			/* Issue a Stop Command */
+			gmbus_wait_event_one(HW_WAIT);
+			WRITE_GMCH_REG(GMBUS1, STO | SW_RDY | ddc_addr);
+			gmbus_wait_event_one(HW_RDY);
+			gmbus_wait_event_zero(GA);
+			gmbus_error_handler();
+			WRITE_GMCH_REG(GMBUS1, SW_RDY);
+			WRITE_GMCH_REG(GMBUS1, SW_CLR_INT);
+			WRITE_GMCH_REG(GMBUS1, 0);
+			WRITE_GMCH_REG(GMBUS5, 0);
+			WRITE_GMCH_REG(GMBUS0, 0);
+			/*...................................................................... */
+			return 0;
+		}
+		while (reg_list[reg_num].reg != PD_REG_LIST_END) {
+
+			if (! gmbus_write_reg(dab, reg_list[reg_num].reg,
+					(unsigned char)reg_list[reg_num].value)) {
+
+				EMGD_DEBUG("Error ! i2c_write_reg_list_tnc : gmbus_write_reg() failed, reg_num=%lu",
+					reg_num);
+
+				return 1;
+			}
+
+			reg_num++;
+		}
+	}
+
+	return 0;
+}
+
+/*!
+ * gmbus_init initializes the GMBUS controller with specified bus and speed
+ *
+ * @param i2c_bus sDVO B/C Reg/DDC or Analog DDC
+ * @param i2c_speed 50/100/400/1000 Khz
+ *
+ * @return TRUE(1) on success
+ * @return FALSE(0) on failure
+ */
+static int gmbus_init(unsigned long i2c_bus,
+	unsigned long i2c_speed)
+{
+	gmbus_pins_pair_t pin_pair;
+	gmbus_speed_t bus_speed;
+
+	switch (i2c_bus) {
+
+	case GMBUS_DVO_REG :
+	case GMBUS_DVOB_DDC :
+		pin_pair = GMBUS_PINS_SDVO;
+		break;
+
+	default :
+		EMGD_ERROR("Error ! gmbus_init : Invalid i2c_bus=0x%lx", i2c_bus);
+		return 0;
+	}
+
+	switch (i2c_speed) {
+
+	case 50 :		/* Slow speed */
+		bus_speed = GMBUS_SPEED_50K;
+		break;
+
+	case 400 :		/* SPD */
+		bus_speed = GMBUS_SPEED_400K;
+		break;
+
+	case 1000 :     /* sDVO Registers */
+		//bus_speed = GMBUS_SPEED_1000K;
+		bus_speed = GMBUS_SPEED_400K;
+		break;
+
+	case 100 :      /* DDC */
+	default :
+		bus_speed = GMBUS_SPEED_100K;
+		break;
+	}
+
+	WRITE_GMCH_REG(GMBUS5, 0);   /* Clear the word index reg */
+	WRITE_GMCH_REG(GMBUS0, pin_pair | bus_speed);
+
+	return 1;
+}
+
+/*!
+ * gmbus_wait_event_zero waits for specified GMBUS2 register bit to be deasserted
+ *
+ * @param bit
+ *
+ * @return TRUE(1) on success. The bit was deasserted in the specified timeout period
+ * @return FALSE(0) on failure
+ */
+static int gmbus_wait_event_zero(unsigned long bit)
+{
+	unsigned long i;
+	unsigned long status;
+
+	for (i = 0; i < 0x1000; i++) {
+
+		status = READ_GMCH_REG(GMBUS2);
+
+		if ((status & bit) == 0) {
+
+			return 1;
+		}
+	}
+
+	EMGD_DEBUG("Error ! gmbus_wait_event_zero : Failed : bit=0x%lx, status=0x%lx",
+		bit, status);
+
+	return 0;
+}
+
+/*!
+ * gmbus_wait_event_one wait for specified GMBUS2 register bits to be asserted
+ *
+ * @param bit
+ *
+ * @return TRUE(1) on success. The bit was asserted in the specified timeout period
+ * @return FALSE(0) on failure
+ */
+static int gmbus_wait_event_one(unsigned long bit)
+{
+	unsigned long i;
+	unsigned long status;
+
+	for (i = 0; i < 0x10000; i++) {
+
+		status = READ_GMCH_REG(GMBUS2);
+		if ((status & bit) != 0) {
+
+			return 1;
+		}
+	}
+
+	EMGD_DEBUG("Error ! gmbus_wait_event_one : Failed : bit=0x%lx, status=0x%lx",
+		bit, status);
+
+	return 0;
+}
+
+/*!
+ * gmbus_error_handler attempts to recover from timeout error
+ *
+ *
+ * @return TRUE(1) error was detected and handled
+ * @return FALSE(0) there was no error
+ */
+static int gmbus_error_handler(void)
+{
+	unsigned long status = READ_GMCH_REG(GMBUS2);
+
+	/* Clear the SW_INT, wait for HWRDY and GMBus active (GA) */
+	if ((status & HW_BUS_ERR) || (status & HW_TMOUT)) {
+
+		EMGD_DEBUG("Error ! gmbus_error_handler : Resolving error=0x%lx",
+			status);
+
+		WRITE_GMCH_REG(GMBUS1, SW_RDY);
+		WRITE_GMCH_REG(GMBUS1, SW_CLR_INT);
+		WRITE_GMCH_REG(GMBUS1, 0);
+
+		gmbus_wait_event_zero(GA);
+
+		return 1;	/* Handled the error */
+	}
+
+	return 0;	/* There was no error */
+}
+
+/*!
+ * Assemble 32 bit GMBUS1 command
+ *
+ * @param slave_addr 0x70/0x72
+ * @param index 0 - 256
+ * @param num_bytes Bytes to transfer
+ * @param flags Bits 25-31 of GMBUS1
+ * @param i2c_dir I2C_READ / I2C_WRITE
+ *
+ * @return The assembled command
+ */
+static unsigned long gmbus_assemble_command(unsigned long slave_addr, unsigned long index,
+	unsigned long num_bytes, unsigned long flags,
+	i2c_bus_dir_t i2c_dir)
+{
+	unsigned long cmd = flags | ENIDX | ENT | (num_bytes << 16) | (index << 8) |
+						slave_addr | i2c_dir;
+
+	return cmd;
+}
+
+/*!
+ * gmbus_send_pkt transmits a block a data to specified i2c slave device
+ *
+ * @param slave_addr I2C device address
+ * @param index Starting i2c register index
+ * @param pkt_size 1 - 508 bytes
+ * @param pkt Bytes to send
+ *
+ * @return TRUE(1) if successful in sending the specified number of bytes
+ * @return FALSE(0) on failure
+ */
+static int gmbus_send_pkt(unsigned long slave_addr, unsigned long index,
+	unsigned long pkt_size, void *pkt)
+{
+	unsigned long gmbus1_cmd;
+	unsigned long bytes_sent;
+	unsigned long *data;
+
+	if ((pkt_size == 0) || (pkt == NULL) || (pkt_size > 508)) {
+
+		return 0;
+	}
+
+	data = (unsigned long *)pkt;
+
+	/*...................................................................... */
+	gmbus_error_handler();
+
+	gmbus1_cmd = gmbus_assemble_command(slave_addr, index, pkt_size,
+										STA, I2C_WRITE);
+	if (pkt_size <= 4) {
+
+		gmbus1_cmd |= SW_RDY;
+	}
+
+	/*...................................................................... */
+	bytes_sent = 0;
+
+	do {
+
+		WRITE_GMCH_REG(GMBUS3, *data);
+
+		if (bytes_sent == 0) {
+
+			WRITE_GMCH_REG(GMBUS1, gmbus1_cmd);
+		}
+
+		if (! gmbus_wait_event_one(HW_RDY)) {
+
+			EMGD_DEBUG("Error ! gmbus_send_pkt : Failed to get HW_RDY, bytes_sent=%ld",
+				bytes_sent);
+
+			return 0;
+		}
+
+		if (gmbus_error_handler()) {
+
+			EMGD_DEBUG("Error ! gmbus_send_pkt : gmbus error, bytes_sent=%ld",
+				bytes_sent);
+
+			return 0;
+		}
+
+		data++;
+
+		if (pkt_size >= 4) {
+			bytes_sent += 4;
+
+		} else {
+			bytes_sent += pkt_size;
+		}
+
+	} while (bytes_sent < pkt_size);
+
+	/*...................................................................... */
+	if (bytes_sent != pkt_size) {
+
+		return 0;
+
+	} else {
+
+		return 1;
+	}
+}
+
+/*!
+ * gmbus_recv_pkt reads a block of data from specified i2c slave device
+ *
+ * @param slave_addr I2C device address
+ * @param index Starting i2c register index
+ * @param pkt_size 1 - 508 bytes
+ * @param pkt Bytes to send
+ *
+ * @return TRUE(1) if successful in receiving specified number of bytes
+ * @return FALSE(0) on failure
+ */
+static int gmbus_recv_pkt(unsigned long slave_addr, unsigned long index,
+	unsigned long pkt_size, void FAR *pkt)
+{
+	unsigned long gmbus1_cmd;
+	unsigned long bytes_rcvd;
+	unsigned long FAR *data;
+
+	if ((pkt_size == 0) || (pkt == NULL) || (pkt_size > 508)) {
+
+		return 0;
+	}
+
+	data = (unsigned long FAR *)pkt;
+
+	/*...................................................................... */
+	gmbus_error_handler();
+
+	/* Program the command */
+	gmbus1_cmd = gmbus_assemble_command(slave_addr, index, pkt_size,
+										STA | SW_RDY, I2C_READ);
+	WRITE_GMCH_REG(GMBUS1, gmbus1_cmd);
+
+	/*...................................................................... */
+	bytes_rcvd = 0;
+	do {
+
+		unsigned long gmbus3_data;
+		unsigned long bytes_left = pkt_size - bytes_rcvd;
+
+		if (! gmbus_wait_event_one(HW_RDY)) {
+
+			EMGD_DEBUG("Error ! gmbus_recv_pkt : Failed to get HW_RDY, "
+				"bytes_rcvd=%ld", bytes_rcvd);
+			break;
+		}
+
+		if (gmbus_error_handler()) {
+
+			EMGD_DEBUG("Error ! gmbus_recv_pkt : gmbus error, bytes_rcvd=%ld",
+				bytes_rcvd);
+			break;
+		}
+
+		gmbus3_data = READ_GMCH_REG(GMBUS3);
+
+		switch (bytes_left) {
+
+		case 1 :
+			*(unsigned char *)data = (unsigned char)gmbus3_data;
+			break;
+
+		case 2 :
+			*(unsigned short *)data = (unsigned short)gmbus3_data;
+			break;
+
+		case 3 :
+		{
+			unsigned char *dest = (unsigned char *)data;
+			 unsigned char *src  = (unsigned char *)&(gmbus3_data);
+			dest[0] = src[0];
+			dest[1] = src[1];
+			dest[2] = src[2];
+
+			break;
+		}
+
+		default :	/* >= 4 */
+			*data = gmbus3_data;
+			break;
+		}
+
+		if (bytes_left > 4) {
+			bytes_rcvd += 4;
+			data++;
+
+		} else {
+			bytes_rcvd += bytes_left;
+
+		}
+
+	} while (bytes_rcvd < pkt_size);
+
+	/*...................................................................... */
+	if (bytes_rcvd < pkt_size) {
+		return 0;
+
+	} else {
+		return 1;
+	}
+}
+
+/*!
+ * gmbus_set_control_bus_switch sends sDVO command to switch i2c bus to read EDID
+ * or SPD data
+ *
+ * @param slave_addr sDVO device address (0x70/0x72)
+ * @param ddc_addr DDC1_ADDR/DDC2_ADDR
+ *
+ * @return TRUE(1) if successful in sending the opcode
+ * @return FALSE(0) on failure
+ */
+static int gmbus_set_control_bus_switch(unsigned long slave_addr,
+	gmbus_ddc_addr_t ddc_addr)
+{
+	unsigned char data;
+	sdvo_bus_switch_t bus_switch;
+	int retry;
+
+	bus_switch = SDVO_BUS_DDC1;
+
+	/*...................................................................... */
+	/*	Transmit the Arguments */
+	if (! gmbus_send_pkt(slave_addr, SDVO_INDEX_PARAM_1, 1, &bus_switch)) {
+
+		EMGD_DEBUG("Error ! gmbus_set_control_bus_switch : gmbus_send_pkt() failed");
+
+		return 0;
+	}
+
+	/*...................................................................... */
+	/* Generate I2C stop cycle */
+	gmbus_wait_event_one(HW_WAIT);
+	WRITE_GMCH_REG(GMBUS1, STO | SW_RDY | slave_addr);
+	gmbus_wait_event_one(HW_RDY);
+	gmbus_wait_event_zero(GA);
+
+	/*...................................................................... */
+	/* Transmit the Opcode */
+	data = SDVO_OPCODE_BUS_SWITCH;
+	if (! gmbus_send_pkt(slave_addr, SDVO_INDEX_OPCODE, 1, &data)) {
+
+		EMGD_DEBUG("Error ! gmbus_set_control_bus_switch : gmbus_send_pkt(Opcode)"
+				 " failed");
+
+		return 0;
+	}
+
+	/*...................................................................... */
+	/* Read Status */
+	for (retry = 0; retry < 3; retry++) {
+		if (! gmbus_recv_pkt(slave_addr, SDVO_INDEX_STATUS, 1, &data)) {
+
+			continue;
+		}
+
+		if (data != SDVO_STATUS_PENDING) {
+
+			break;
+		}
+	}
+
+	/*...................................................................... */
+	/* Send Stop */
+	gmbus_wait_event_one(HW_WAIT);
+	WRITE_GMCH_REG(GMBUS1, STO | SW_RDY | slave_addr);
+	gmbus_wait_event_one(HW_RDY);
+	gmbus_wait_event_zero(GA);
+
+	/*...................................................................... */
+	if (data != SDVO_STATUS_SUCCESS) {
+
+		EMGD_DEBUG("Error ! gmbus_set_control_bus_switch : Opcode Bus Switch failed");
+
+		return 0;
+	}
+
+	return 1;
+}
+
+/*!
+ * gmbus_read_edid reads specified number of Edid data bytes
+ *
+ * @param ddc_addr 0xA0/0xA2 (DDC1/DDC2)
+ * @param slave_addr 0x70/0x72 (sDVOB, sDVOC), 0 Analog
+ * @param index i2c register index
+ * @param num_bytes <= 508
+ * @param buffer Edid data read from the display
+ *
+ * @return TRUE(1) if successful in reading Edid
+ * @return FALSE(0) on failure
+ */
+static int gmbus_read_edid(unsigned long ddc_addr,
+	unsigned long slave_addr,
+	unsigned long index,
+	unsigned long num_bytes,
+	unsigned char FAR *buffer)
+{
+	int status;
+
+	if (slave_addr == SDVOB_ADDR) {
+
+		if (! gmbus_set_control_bus_switch(slave_addr, ddc_addr)) {
+
+			EMGD_DEBUG("Error ! gmbus_read_edid : gmbus_set_control_bus_switch()"
+					 " failed");
+
+			return 0;
+		}
+	} else {
+		/*	Reset the bus */
+		gmbus_recv_pkt(ddc_addr, 0, 1, buffer);
+	}
+
+	status = gmbus_recv_pkt(ddc_addr, index, num_bytes, buffer);
+	if (! status) {
+
+		EMGD_DEBUG("Error ! gmbus_read_edid : gmbus_recv_pkt() failed");
+	}
+
+	/*...................................................................... */
+	/* Issue a Stop Command */
+
+	gmbus_wait_event_one(HW_WAIT);
+	WRITE_GMCH_REG(GMBUS1, STO | SW_RDY | ddc_addr);
+	gmbus_wait_event_one(HW_RDY);
+
+	gmbus_wait_event_zero(GA);
+
+	gmbus_error_handler();
+	WRITE_GMCH_REG(GMBUS1, SW_RDY);
+	WRITE_GMCH_REG(GMBUS1, SW_CLR_INT);
+	WRITE_GMCH_REG(GMBUS1, 0);
+	WRITE_GMCH_REG(GMBUS5, 0);
+	WRITE_GMCH_REG(GMBUS0, 0);
+
+	/*...................................................................... */
+	return status;
+}
+
+/*!
+ * gmbus_read_reg reads one i2c register
+ *
+ * @param slave_addr 0x70/0x72 (sDVOB, sDVOC)
+ * @param index i2c register index
+ * @param data register data
+ *
+ * @return TRUE(1) if successful in reading the i2c register
+ * @return FALSE(0) on failure
+ */
+static int gmbus_read_reg(unsigned long slave_addr,
+	unsigned long index,
+	unsigned char FAR *data)
+{
+	unsigned long gmbus1_cmd;
+
+	WRITE_GMCH_REG(GMBUS5, 0x0);		/* Clear Word Index register */
+
+	if (! gmbus_wait_event_zero(GA)) {
+
+		EMGD_DEBUG("Error ! gmbus_read_reg : Failed to get GA(1)");
+
+		return 0;
+	}
+
+	gmbus1_cmd = gmbus_assemble_command(slave_addr, index, 1,
+										STO | STA, I2C_READ);
+	WRITE_GMCH_REG(GMBUS1, gmbus1_cmd);
+
+	if (! gmbus_wait_event_zero(GA)) {
+
+		EMGD_DEBUG("Error ! gmbus_read_reg : Failed to get GA(2)");
+
+		return 0;
+	}
+
+	*data = (unsigned char)READ_GMCH_REG(GMBUS3);
+
+	return 1;
+}
+
+/*!
+ * gmbus_write_reg writes one i2c register
+ *
+ * @param slave_addr 0x70/0x72 (sDVOB, sDVOC)
+ * @param index i2c register index
+ * @param data register data
+ *
+ * @return TRUE(1) if successful in updating the i2c register
+ * @return FALSE(0) if failed to update the register
+ */
+static int gmbus_write_reg(unsigned long slave_addr,
+	unsigned long index,
+	unsigned char data)
+{
+	unsigned long gmbus1_cmd;
+
+	WRITE_GMCH_REG(GMBUS5, 0x0);		/* Clear Word Index register */
+
+	if (! gmbus_wait_event_zero(GA)) {
+
+		EMGD_DEBUG("Error ! gmbus_write_reg : Failed to get GA(1)");
+
+		return 0;
+	}
+
+	WRITE_GMCH_REG(GMBUS3, data);
+
+	gmbus1_cmd = gmbus_assemble_command(slave_addr, index, 1,
+										STO | STA, I2C_WRITE);
+	WRITE_GMCH_REG(GMBUS1, gmbus1_cmd);
+
+	if (! gmbus_wait_event_zero(GA)) {
+
+		EMGD_DEBUG("Error ! gmbus_write_reg : Failed to get GA(2)");
+		return 0;
+	}
+
+	return 1;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/drm/drm_emgd_private.h b/drivers/gpu/drm/emgd/emgd/drm/drm_emgd_private.h
new file mode 100644
index 0000000..d6d6819
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/drm_emgd_private.h
@@ -0,0 +1,176 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: drm_emgd_private.h
+ * $Revision: 1.22 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains the EMGD-specific drm_device.dev_private structure,
+ *  which is used to share data with the EMGD-specific, IMG 3rd-Party Display
+ *  Driver (3DD, implimented in the
+ *  "egd_drm/pvr/services4/3rdparty/emgd_displayclass" directory).
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _DRM_EMGD_PRIVATE_H_
+#define _DRM_EMGD_PRIVATE_H_
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_fb_helper.h>
+#include "mode.h"
+#include "context.h"
+#include "emgd_drv.h"
+
+struct _drm_emgd_private;
+
+
+/* FIXME: This define should not be here.  Find a better place to put it */
+#define PSB_GATT_RESOURCE   2
+
+/**
+ * This enum is used to record the currently-saved register state (e.g. for VT
+ * switching)--either the Linux console's state is saved (i.e. the X server is
+ * active), or the X server's state is saved (i.e. the Linux console is
+ * active).
+ */
+typedef enum _drm_emgd_saved_state {
+	CONSOLE_STATE_SAVED = 0,
+	X_SERVER_STATE_SAVED = 1,
+} drm_emgd_saved_state;
+
+
+/**
+ * This structure allows the EMGD-proper code to communicate information and
+ * function pointers to the IMG 3rd-Party Display Driver (mrstlfb).
+ */
+typedef struct _drm_emgd_private {
+	/** Non-zero if the HAL is running */
+	int hal_running;
+
+	/**
+	 * Which register state is currently saved for VT switches (X or the
+	 * console; note: the opposite is what's actively installed in the
+	 * hardware)
+	 */
+	drm_emgd_saved_state saved_registers;
+
+	/**
+	 * Saved state of the console, when suspending (or hibernating) the system.
+	 * emgd_driver_suspend() allocates this, and emgd_driver_resume() frees
+	 * this.
+	 */
+	void *suspended_state;
+
+	/**
+	 * A flag which emgd_driver_pre_init() sets and emgd_alter_displays()
+	 * clears.  If set (i.e. to 1), this indicates that emgd_alter_displays()
+	 * must power on the port drivers' hardware.
+	 */
+	int must_power_on_ports;
+
+	/** Non-zero if the X server is running (i.e. PVR can't do mode changes) */
+	int xserver_running;
+
+	/**
+	 * Function to re-initialize the 3DD's data structures, after calls to
+	 * alter_displays()
+	 */
+	int (*reinit_3dd)(struct drm_device *dev);
+
+	/**
+	 * Function to invalidate the flip-chains assosciated with a display (or all
+	 * displays). Called from igd_alter_displays before a possible mode_change
+	 */
+	int (*invalidate_flip_chains)(int display);
+
+
+	/** The context is set during the DRM module load function. */
+	igd_context_t *context;
+
+	/* The selected DC is copied to here each time alter_displays() is called
+	 * via an ioctl.
+	 */
+	unsigned long dc;
+
+	/**
+	 * The port number of the primary display handle is copied to here each
+	 * time alter_displays() is called via an ioctl.
+	 */
+	unsigned short primary_port_number;
+
+	/**
+	 * The primary display handle is copied to here each time alter_displays()
+	 * is called via an ioctl.
+	 */
+	igd_display_h primary;
+
+	/**
+	 * The port number of the secondary display handle is copied to here each
+	 * time alter_displays() is called via an ioctl.
+	 */
+	unsigned short secondary_port_number;
+
+	/**
+	 * The secondary display handle is copied to here each time alter_displays()
+	 * is called via an ioctl.
+	 */
+	igd_display_h secondary;
+
+	/**
+	 * Store the device information so it can be passed back to userspace
+	 * callers via an ioctl.
+	 */
+	igd_init_info_t *init_info;
+
+	/** TODO:  May use this in future.
+	 * MSVDX
+	 */
+	void *msvdx_private;
+
+	/*
+	 * GTT offset of initial framebuffer.  The initial framebuffer is a special
+	 * case in that it is allocated directly by the GMM at system startup
+	 * before the PVR services are initialized.  As such, it has no PVR
+	 * meminfo that can be used as a handle to refer to it; functions that take
+	 * a framebuffer will treat a handle of 0 as referring to the initial
+	 * framebuffer and then pull the GTT offset from here.
+	 */
+	//unsigned long initfb_offset;
+	igd_framebuffer_info_t initfb_info;
+
+	/* fbdev is removed from drm_framebuffer in 2.6.35 so access it here */
+	struct fb_info    *fbdev;
+	emgd_crtc_t       *crtcs[IGD_MAX_PIPES];
+	int                num_crtc;
+	emgd_fbdev_t      *emgd_fbdev;
+	bool               mode_config_initialized;
+	struct drm_device *ddev;
+	bool               kms_enabled;
+	int qb_seamless; /* Store the state of seamless/quickboot */
+
+	/* The fd of the drm master - used to send vblank events to userspace */
+	struct drm_file   *drm_master_fd;  
+} drm_emgd_priv_t;
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_connector.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_connector.c
new file mode 100644
index 0000000..280f839
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_connector.c
@@ -0,0 +1,512 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_connector.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:
+ *  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       = 0;
+	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 can do some basic checks here, but it is better to call
+     * match_mode() in the display/mode module because that function does
+     * a much more thorough check */
+
+
+
+        EMGD_TRACE_EXIT;
+
+        return MODE_OK;
+}
+
+
+
+/**
+ * emgd_connector_best_encoder
+ *
+ * Returns the best encoder for the given connector.  In EMGD the connector is
+ * fixed to the encoder.
+ *
+ * @param connector (IN) the connector to be analyzed.
+ *
+ * @return Encoder onto which the connector is fixed on.
+ */
+static struct drm_encoder *emgd_connector_best_encoder(
+                struct drm_connector *connector)
+{
+        emgd_connector_t *emgd_connector;
+
+        EMGD_TRACE_ENTER;
+
+        emgd_connector = container_of(connector, emgd_connector_t, base);
+
+        EMGD_TRACE_EXIT;
+
+        return &emgd_connector->encoder->base;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_crtc.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_crtc.c
new file mode 100644
index 0000000..76e0235
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_crtc.c
@@ -0,0 +1,997 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_crtc.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:
+ *  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 <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;
+
+
+	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");
+		} 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->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->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)
+{
+	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 (port == devpriv->primary_port_number) {
+		crtcnum = 0;
+	} else if (port == devpriv->secondary_port_number) {
+		crtcnum = 1;
+	} else {
+		return 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.pitch;
+		igd_surface.width        = crtc->newfb->base.width;
+		igd_surface.height       = crtc->newfb->base.height;
+		igd_surface.pixel_format = IGD_PF_ARGB32;
+
+		igd_context->dispatch.set_surface(
+			crtc->igd_pipe->owner,
+			IGD_PRIORITY_NORMAL,
+			IGD_BUFFER_DISPLAY,
+			&igd_surface,
+			NULL, /* Not used */
+			0);
+
+		/* Flip issued.  No need to requeue the work. */
+		crtc->flip_work_queued = 0;
+
+		/*
+		 * If a userspace event was requested for this flip, request vblank
+		 * interrupts if they aren't already on.
+		 */
+		if (crtc->flip_event) {
+			/* Request vblank events (or inc the refcount if they're already on) */
+			ret = drm_vblank_get(crtc->base.dev, crtcnum);
+			if (ret) {
+				EMGD_ERROR("Failed enable vblanks");
+				return;
+			}
+			crtc->vblank_expected = 1;
+		} else {
+			/*
+			 * No userspace event; the flip is complete as far as we're
+			 * concerned.  Clear the "in progress of switching to fb" field.
+			 */
+			crtc->newfb = NULL;
+		}
+
+	} else {
+		/* Rendering not complete.  Requeue the work task. */
+		schedule_work(w);
+	}
+
+	spin_unlock_irqrestore(&crtc->crtc_lock, flags);
+}
+
+
+/**
+ * emgd_crtc_page_flip
+ *
+ * Page flip ioctl handler.  The ioctl simply dispatches a workqueue task
+ * which will wait until current rendering against the new framebuffer
+ * is complete, then issue the actual flip.  This ioctl should return
+ * immediately, allowing pipelining of subsequent CPU execution with
+ * the outstanding rendering happening against this framebuffer.
+ *
+ * @param crtc  (INOUT) The pipe to put the new framebuffer on
+ * @param fb    (IN)    Framebuffer to flip to
+ * @param event (IN)    Event to signal when flip has been completed
+ *
+ * @return
+ *
+ * State upon entry:
+ *  * No constraint on newfb
+ *  * No constraint on flip_event
+ *  * No constraint on flip_work_queued
+ *  * No constraint on vblank_expected
+ *
+ * State upon exit:
+ *  * newfb is non-NULL
+ *  * no constraint on flip_event
+ *  * flip_work_queued is TRUE
+ *  * vblank_expected is FALSE
+ */
+static int emgd_crtc_page_flip(struct drm_crtc *crtc,
+                                struct drm_framebuffer *fb,
+                                struct drm_pending_vblank_event *event)
+{
+	emgd_crtc_t        *emgd_crtc;
+	emgd_framebuffer_t *emgd_fb;
+	drm_emgd_priv_t    *dev_priv;
+	igd_context_t      *igd_context;
+	unsigned int crtcnum;
+	unsigned long flags;
+	struct drm_pending_vblank_event *e;
+	struct timeval now;
+	PVRSRV_KERNEL_MEM_INFO *meminfo;
+	PVRSRV_SYNC_DATA *syncdata;
+
+	EMGD_TRACE_ENTER;
+
+	emgd_crtc   = container_of(crtc, emgd_crtc_t, base);
+	dev_priv    = (drm_emgd_priv_t *) crtc->dev->dev_private;
+	igd_context = dev_priv->context;
+	emgd_fb     = container_of(fb, emgd_framebuffer_t, base);
+	crtcnum = (emgd_crtc == dev_priv->crtcs[0]) ? 0 : 1;
+
+	/*
+	 * Protect updates to the CRTC structure. We don't want this code to
+	 * overlap with either the workqueue task or the vblank handler.
+	 */
+	spin_lock_irqsave(&emgd_crtc->crtc_lock, flags);
+
+	/*
+	 * Was there a pending userspace event for a previous flip request?  If
+	 * so, just send the completion back now.  We're essentially cancelling
+	 * the previous flip (it will never show up on the display), but we don't
+	 * want userspace to get confused by not receiving notification.  We'll
+	 * also decrement our vblank request if we'd already scheduled on for
+	 * cleanup.
+	 */
+	if ((e = emgd_crtc->flip_event) != NULL) {
+		do_gettimeofday(&now);
+		e->event.sequence = 0;
+		e->event.tv_sec = now.tv_sec;
+		e->event.tv_usec = now.tv_usec;
+		list_add_tail(&e->base.link, &e->base.file_priv->event_list);
+		wake_up_interruptible(&e->base.file_priv->event_wait);
+		emgd_crtc->flip_event = NULL;
+
+		/*
+		 * If the work task had completed and actually programmed the
+		 * registers, it had also requested a vblank callback.  Cancel
+		 * that as well since we've already taken care of the necessary
+		 * cleanup.  Note that vblanks are only requested when we actually
+		 * have a userspace event to send back.
+		 */
+		if (emgd_crtc->vblank_expected) {
+			drm_vblank_put(crtc->dev, crtcnum);
+			emgd_crtc->vblank_expected = 0;
+		}
+	}
+
+	/* Update the CRTC's "target framebuffer" field. */
+	emgd_crtc->newfb = emgd_fb;
+	emgd_crtc->flip_event = event;
+
+	/*
+	 * Set the number of rendering operations that need to complete before we
+	 * can flip to this buffer.  I.e., we don't need render to completely
+	 * quiesce, we can flip as soon as any operations that are outstanding
+	 * right now complete, even if more rendering ops get added to the pipeline
+	 * after we return.
+	 */
+	meminfo = (PVRSRV_KERNEL_MEM_INFO *)emgd_fb->pvr_meminfo;
+	syncdata = meminfo->psKernelSyncInfo->psSyncData;
+	emgd_crtc->render_complete_at = syncdata->ui32WriteOpsPending;
+
+	/*
+	 * If work is already scheduled, nothing more to do here; the
+	 * already-scheduled work will see the new values we set next time it wakes
+	 * up and will act upon them.  However if work is not scheduled, then
+	 * we need to schedule it now.
+	 */
+	if (!emgd_crtc->flip_work_queued) {
+		schedule_work(&emgd_crtc->flip_work);
+		emgd_crtc->flip_work_queued = 1;
+	}
+
+	/* Move the FB currently associated with the CRTC to the new FB */
+	crtc->fb = fb;
+
+	/* Done updating CRTC structure */
+	spin_unlock_irqrestore(&emgd_crtc->crtc_lock, flags);
+
+	EMGD_TRACE_EXIT;
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_drv.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_drv.c
new file mode 100644
index 0000000..92f70a7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_drv.c
@@ -0,0 +1,2472 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_drv.c
+ * $Revision: 1.145 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF 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"
+/*
+ * 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>
+
+/* 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.
+	 */
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_ALTER_CURSOR, emgd_alter_cursor,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_ALTER_CURSOR_POS, emgd_alter_cursor_pos,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_ALTER_DISPLAYS, emgd_alter_displays,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_ALTER_OVL, emgd_alter_ovl, DRM_MASTER),
+	/* 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),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_APPCTX_ALLOC, emgd_appcontext_alloc,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_APPCTX_FREE, emgd_appcontext_free,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_DRIVER_SAVE_RESTORE, emgd_driver_save_restore,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_ENABLE_PORT, emgd_enable_port, DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_ATTRS, emgd_get_attrs, DRM_MASTER),
+	/* 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),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_DRM_CONFIG, emgd_get_drm_config,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_EDID_BLOCK, emgd_get_EDID_block,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_EDID_INFO, emgd_get_EDID_info,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_PIXELFORMATS, emgd_get_pixelformats,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_PORT_INFO, emgd_get_port_info,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GMM_ALLOC_REGION, emgd_gmm_alloc_region,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GMM_ALLOC_SURFACE, emgd_gmm_alloc_surface,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GMM_GET_NUM_SURFACE, emgd_gmm_get_num_surface,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GMM_GET_SURFACE_LIST,
+		emgd_gmm_get_surface_list,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GMM_FREE, emgd_gmm_free,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GMM_FLUSH_CACHE, emgd_gmm_flush_cache,
+		DRM_MASTER),
+	/*
+	 * 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, 0),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_RESERVED_2, PVRDRM_Dummy_ioctl, 0),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_RESERVED_3, PVRDRM_Dummy_ioctl, 0),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_RESERVED_4, PVRDRMIsMaster, DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_RESERVED_5, PVRDRMUnprivCmd, 0),
+
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_PAN_DISPLAY, emgd_pan_display,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_POWER_DISPLAY, emgd_power_display,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_PWR_ALTER, emgd_pwr_alter, DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_QUERY_DC, emgd_query_dc,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_QUERY_MAX_SIZE_OVL, emgd_query_max_size_ovl,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_QUERY_OVL, emgd_query_ovl, DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_QUERY_MODE_LIST, emgd_query_mode_list,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_GOLDEN_HTOTAL, emgd_get_golden_htotal,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_CONTROL_PLANE_FORMAT, emgd_control_plane_format,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_SET_OVERLAY_DISPLAY, emgd_set_overlay_display,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_QUERY_2D_CAPS_HWHINT, emgd_query_2d_caps_hwhint,
+		DRM_MASTER),
+	/*
+	 * 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),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_SET_PALETTE_ENTRY, emgd_set_palette_entry,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_SET_SURFACE, emgd_set_surface, DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_SYNC, emgd_sync, DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_DRIVER_PRE_INIT, emgd_driver_pre_init,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_DRIVER_GET_PORTS, emgd_driver_get_ports,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_OVL_INIT_PARAMS, emgd_get_ovl_init_params,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_PAGE_LIST, emgd_get_page_list,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_START_PVRSRV, emgd_start_pvrsrv,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_TEST_PVRSRV, emgd_test_pvrsrv,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_CHIPSET_INFO, emgd_get_chipset_info,
+		DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_DIHCLONE_SET_SURFACE, emgd_dihclone_set_surface, DRM_MASTER),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_PREINIT_MMU, emgd_preinit_mmu, DRM_MASTER),
+
+	/*
+	 * For VIDEO (MSVDX/TOPAZ
+	 */
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_VIDEO_CMD_BUF, emgd_video_cmd_buf,
+		DRM_AUTH),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_INIT_VIDEO, emgd_init_video,
+		DRM_AUTH),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_GET_DEVICE_INFO, emgd_get_device_info,
+		DRM_AUTH),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_VIDEO_GET_INFO, emgd_video_get_info,
+		DRM_AUTH),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_VIDEO_FLUSH_TLB, emgd_video_flush_tlb,
+		DRM_AUTH),
+
+	/* For Buffer Class of Texture Stream */
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_INIT, emgd_bc_ts_cmd_init,
+		DRM_AUTH),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_UNINIT, emgd_bc_ts_cmd_uninit,
+		DRM_AUTH),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_REQUEST_BUFFERS, emgd_bc_ts_cmd_request_buffers,
+		DRM_AUTH),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_RELEASE_BUFFERS, emgd_bc_ts_cmd_release_buffers,
+		DRM_AUTH),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_SET_BUFFER_INFO, emgd_bc_ts_set_buffer_info,
+		DRM_AUTH),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_GET_BUFFERS_COUNT, emgd_bc_ts_get_buffers_count,
+		DRM_AUTH),
+	EMGD_IOCTL_DEF(DRM_IOCTL_IGD_BC_TS_GET_BUFFER_INDEX, emgd_bc_ts_get_buffer_index,
+		DRM_AUTH),
+};
+
+static int emgd_max_ioctl = DRM_ARRAY_SIZE(emgd_ioctl);
+
+
+
+/*
+ * NOTE: The next part of this file are EMGD-specific DRM functions, exported to
+ * the generic DRM code via the drm_driver struct:
+ */
+
+
+extern igd_driver_h handle;
+/** This is the dispatch table for the HAL.  It is cached for quick access. */
+extern igd_dispatch_t *dispatch;
+
+
+/**
+ * The driver handle for talking with the HAL, within the DRM/kernel code.
+ *
+ * This is a "real handle" as opposed to the "fake handle" in user-space.
+ * Notice that there's only one handle, as the secondary device shares this
+ * handle.
+ */
+static igd_driver_h drm_HAL_handle = NULL;
+
+/**
+ * This is the drm_HAL_handle cast to an igd_context_t.  It is cached for quick
+ * access.
+ */
+static igd_context_t *drm_HAL_context = NULL;
+
+/**
+ * This is the dispatch table for the HAL.  It is cached for quick access.
+ */
+static igd_dispatch_t *drm_HAL_dispatch = NULL;
+
+
+
+/*!
+ * 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;
+
+	EMGD_TRACE_ENTER;
+	mutex_lock(&dev->struct_mutex);
+
+	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
+
+/**
+ * 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,
+	.fops = {
+		.owner   = THIS_MODULE,
+		.open    = drm_open,
+		.release = drm_release,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
+		.unlocked_ioctl   = drm_ioctl,
+#else
+		.ioctl   = drm_ioctl,
+#endif
+		.mmap    = emgd_mmap,
+		.poll    = drm_poll,
+		.fasync  = drm_fasync,
+		.read    = drm_read,
+	},
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
+	.pci_driver          = EMGD_PCI_DRIVER,
+#endif
+	.name                = DRIVER_NAME,
+	.desc                = DRIVER_DESC,
+	.date                = DRIVER_DATE,
+	.major               = DRIVER_MAJOR,
+	.minor               = DRIVER_MINOR,
+	.patchlevel          = DRIVER_PATCHLEVEL,
+};
+
+/**
+ * Standard procedure to initialize this kernel module when it is loaded.
+ */
+static int __init emgd_init(void) {
+	int ret;
+	struct pci_dev *our_device;
+
+	printk(KERN_INFO "[EMGD] Initializing Driver.\n");
+	driver.num_ioctls = emgd_max_ioctl;
+
+	/* If init == 1 then we should always set KMS to 0 for US15 */
+
+	if(config_drm.init || drm_emgd_init == 1){
+		
+		/*  Detecting device */
+
+		/* 
+		 * 0x8086 is the intel vendor id and 0x8108 is the 
+		 * US15 device id.
+		 * pci_get_device returns NULL if it is not a PLB.
+		 */
+
+		our_device = pci_get_device(PCI_VENDOR_ID_INTEL, 
+					PCI_DEVICE_ID_VGA_PLB, NULL);
+		
+		if(our_device){
+			EMGD_ERROR("US15 detected. Setting KMS to 0 "
+				"config_drm.kms = %d ", config_drm.kms);
+			config_drm.kms = 0;
+		}
+	}
+
+	if (config_drm.kms && (config_drm.init || drm_emgd_init == 1)) {
+		driver.driver_features |= DRIVER_MODESET;
+	}
+
+	PVRDPFInit();
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+	ret = drm_pci_init(&driver, &emgd_pci_driver);
+#else
+	ret = drm_init(&driver);
+#endif
+	printk(KERN_INFO "[EMGD] Driver Initialized.\n");
+	EMGD_TRACE_EXIT;
+	return ret;
+}
+
+/**
+ * Standard procedure to clean-up this kernel module before it exits & unloads.
+ */
+static void __exit emgd_exit(void) {
+	EMGD_TRACE_ENTER;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+	drm_pci_exit(&driver, &emgd_pci_driver);
+#else
+	drm_exit(&driver);
+#endif
+	EMGD_TRACE_EXIT;
+}
+
+
+module_init(emgd_init);
+module_exit(emgd_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_drv.h b/drivers/gpu/drm/emgd/emgd/drm/emgd_drv.h
new file mode 100644
index 0000000..c7e334a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_drv.h
@@ -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/drivers/gpu/drm/emgd/emgd/drm/emgd_encoder.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_encoder.c
new file mode 100644
index 0000000..72b3d3e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_encoder.c
@@ -0,0 +1,477 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_encoder.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:
+ *  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_encoder_t *emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+	igd_display_port_t *igd_port = emgd_encoder->igd_port;
+	unsigned long       new_port_state;
+
+	EMGD_TRACE_ENTER;
+
+
+	switch(mode) {
+		case DRM_MODE_DPMS_ON:
+			new_port_state = IGD_POWERSTATE_D0;
+			break;
+
+		case DRM_MODE_DPMS_STANDBY:
+		case DRM_MODE_DPMS_SUSPEND:
+		case DRM_MODE_DPMS_OFF:
+			new_port_state = IGD_POWERSTATE_D3;
+			break;
+
+		default:
+			EMGD_ERROR_EXIT("Unsupported DPMS mode");
+			return;
+	}
+
+
+	if (new_port_state == IGD_POWERSTATE_D3 &&
+		emgd_encoder->flags & ENCODER_FLAG_FIRST_DPMS) {
+
+		EMGD_DEBUG("Not setting initial port %lx power to %lx",
+			igd_port->port_number, new_port_state);
+		emgd_encoder->flags &= ~ENCODER_FLAG_FIRST_DPMS;
+	} else {
+		EMGD_DEBUG("Setting port %lx power to %lx",
+			igd_port->port_number, new_port_state);
+		igd_port->pd_driver->set_power(igd_port->pd_context,
+			new_port_state);
+
+		if (new_port_state == IGD_POWERSTATE_D0) {
+			mode_context->kms_dispatch->kms_post_program_port(emgd_encoder,
+				TRUE);
+		}
+	}
+
+	EMGD_TRACE_EXIT;
+}
+
+
+
+/**
+ * emgd_encoder_mode_fixup
+ *
+ * Called before a mode set, takes the input "mode", matches it to the closest
+ * supported mode, then put the supported mode into "adjusted_mode" to let the
+ * caller know.
+ *
+ * Note: We cannot handle centered and scaled mode with this.  To handle this
+ *       we need to program the pipe and the port to different sets of timings.
+ *       The CRTC Helper does not allow this.  It wants to send adjusted_mode
+ *       to both the CRTC and the Encoder.  We can maybe get around this by
+ *       modifying the "mode" parameter, but that is not the right approach.
+ *
+ * @param encoder (IN) Encoder being prepared
+ * @param mode    (IN) Requested mode
+ * @param adjusted_mode (IN) Encoder supported mode
+ *
+ * @return true, false (details TBD)
+ */
+static bool emgd_encoder_mode_fixup(struct drm_encoder *encoder,
+		struct drm_display_mode *mode,
+		struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device      *dev          = NULL;
+	igd_context_t          *context      = NULL;
+	igd_display_port_t     *port         = NULL;
+	igd_framebuffer_info_t *fb_info      = NULL;
+	emgd_encoder_t         *emgd_encoder = NULL;
+	igd_timing_info_t      *timing       = NULL;
+	igd_display_info_t     *pt_info      = NULL;
+	emgd_crtc_t            *emgd_crtc    = NULL;
+	igd_display_pipe_t     *pipe         = NULL;
+	unsigned long           existing_height  = 0;
+	unsigned long           existing_width   = 0;
+	unsigned long           existing_refresh = 0;
+	int                     ret;
+
+	EMGD_TRACE_ENTER;
+
+	/* Check ajusted mode to see if it's valid.  If not, populate it */
+	if (adjusted_mode->crtc_htotal == 0) {
+		EMGD_DEBUG("No valid mode in adjusted mode, setting valid mode");
+		drm_mode_set_crtcinfo(adjusted_mode, 0);
+	}
+
+	dev = encoder->dev;
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+	emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+	port = emgd_encoder->igd_port;
+	if (!port->pt_info) {
+		port->pt_info = kzalloc(sizeof(igd_display_info_t), GFP_KERNEL);
+		if (!port->pt_info) {
+			EMGD_DEBUG("Cannot allocate igd_display_into_t");
+			return false;
+		}
+	}
+	existing_height  = port->pt_info->height;
+	existing_width   = port->pt_info->width;
+	existing_refresh = port->pt_info->refresh;
+	pt_info          = port->pt_info;
+
+	fb_info = kzalloc(sizeof(igd_framebuffer_info_t), GFP_KERNEL);
+	if (!fb_info) {
+		EMGD_DEBUG("Cannot allocate framebuffer info");
+		return false;
+	}
+
+	/* Get the dimension of the framebuffer linked to the CRTC.  If it is
+	 * smaller than the resolution, kms_match_mode will either center it
+	 * or let the encoder hardware scale it */
+	fb_info->width  = encoder->crtc->fb->width;
+	fb_info->height = encoder->crtc->fb->height;
+	EMGD_DEBUG("Setting fb_info to: %dx%d", fb_info->width, fb_info->height);
+
+	pt_info->width        = mode->crtc_hdisplay;
+	pt_info->height       = mode->crtc_vdisplay;
+	pt_info->refresh      = mode->vrefresh;
+	pt_info->dclk         = mode->synth_clock;
+	pt_info->htotal       = mode->crtc_htotal;
+	pt_info->hblank_start = mode->crtc_hblank_start;
+	pt_info->hblank_end   = mode->crtc_hblank_end;
+	pt_info->hsync_start  = mode->crtc_hsync_start;
+	pt_info->hsync_end    = mode->crtc_hsync_end;
+	pt_info->vtotal       = mode->crtc_vtotal;
+	pt_info->vblank_start = mode->crtc_vblank_start;
+	pt_info->vblank_end   = mode->crtc_vblank_end;
+	pt_info->vsync_start  = mode->crtc_vsync_start;
+	pt_info->vsync_end    = mode->crtc_vsync_end;
+	pt_info->mode_number  = mode->clock_index;
+	pt_info->flags        = 0;
+	EMGD_DEBUG("Setting pt_info to: %dx%d", pt_info->width, pt_info->height);
+
+	ret = mode_context->kms_dispatch->kms_match_mode((void *)emgd_encoder,
+		(void *)fb_info, &timing);
+
+	if (!ret) {
+		adjusted_mode->crtc_hdisplay     = timing->width;
+		adjusted_mode->crtc_vdisplay     = timing->height;
+		adjusted_mode->vrefresh          = timing->refresh;
+		adjusted_mode->synth_clock       = timing->dclk;
+		adjusted_mode->crtc_htotal       = timing->htotal;
+		adjusted_mode->crtc_hblank_start = timing->hblank_start;
+		adjusted_mode->crtc_hblank_end   = timing->hblank_end;
+		adjusted_mode->crtc_hsync_start  = timing->hsync_start;
+		adjusted_mode->crtc_hsync_end    = timing->hsync_end;
+		adjusted_mode->crtc_vtotal       = timing->vtotal;
+		adjusted_mode->crtc_vblank_start = timing->vblank_start;
+		adjusted_mode->crtc_vblank_end   = timing->vblank_end;
+		adjusted_mode->crtc_vsync_start  = timing->vsync_start;
+		adjusted_mode->crtc_vsync_end    = timing->vsync_end;
+		adjusted_mode->clock_index       = timing->mode_number;
+		adjusted_mode->private_flags     = timing->mode_info_flags;
+
+		EMGD_DEBUG("(%dx%d@%d)->(%dx%d@%d)",
+			mode->crtc_hdisplay, mode->crtc_vdisplay, mode->vrefresh,
+			adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_vdisplay,
+			adjusted_mode->vrefresh);
+
+		/* Check our new mode against what currently there
+		 * to see if we can do a seamless mode-set
+		 */
+		if (emgd_encoder->flags & ENCODER_FLAG_FIRST_ALTER) {
+			if (mode_context->fw_info) {
+
+				emgd_crtc = container_of(encoder->crtc, emgd_crtc_t, base);
+				pipe = emgd_crtc->igd_pipe;
+
+				existing_width = mode_context->fw_info->
+					timing_arr[pipe->pipe_num].width;
+				existing_height = mode_context->fw_info->
+					timing_arr[pipe->pipe_num].height;
+				existing_refresh = mode_context->fw_info->
+					timing_arr[pipe->pipe_num].refresh;
+
+			}
+		}
+
+		if (adjusted_mode->crtc_hdisplay == existing_width &&
+			adjusted_mode->crtc_vdisplay == existing_height) {
+
+			if (abs(adjusted_mode->vrefresh - existing_refresh) <= 1) {
+				emgd_encoder->flags |= ENCODER_FLAG_SEAMLESS;
+			}
+		}
+	}
+
+	kfree(fb_info);
+
+	EMGD_TRACE_EXIT;
+	return (!ret);
+}
+
+
+
+/**
+ * emgd_encoder_prepare
+ *
+ * Based on the available documentation at the moment, this function gets
+ * called right before a mode change.  Its job is to turn off the display.
+ *
+ * @param encoder (IN) Encoder being prepared
+ *
+ * @return None
+ */
+static void emgd_encoder_prepare(struct drm_encoder *encoder)
+{
+	struct drm_encoder_helper_funcs *encoder_funcs;
+	emgd_encoder_t *emgd_encoder;
+
+	EMGD_TRACE_ENTER;
+
+	emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+
+	if (!(emgd_encoder->flags & ENCODER_FLAG_SEAMLESS)) {
+		encoder_funcs = encoder->helper_private;
+		encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
+	}
+
+	emgd_encoder->flags &= ~ENCODER_FLAG_FIRST_ALTER;
+
+	EMGD_TRACE_EXIT;
+}
+
+
+
+/**
+ * emgd_encoder_commit
+ *
+ * This function commits the mode change sequence by actually programming
+ * the registers.
+ *
+ * @param encoder (IN) Encoder being prepared
+ *
+ * @return None
+ */
+static void emgd_encoder_commit(struct drm_encoder *encoder)
+{
+	struct drm_encoder_helper_funcs *encoder_funcs;
+	emgd_encoder_t     *emgd_encoder = NULL;
+	emgd_crtc_t        *emgd_crtc;
+	igd_display_port_t *port;
+	igd_display_pipe_t *pipe;
+
+	EMGD_TRACE_ENTER;
+
+	emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+
+
+	if (!(emgd_encoder->flags & ENCODER_FLAG_SEAMLESS)) {
+
+		port      = emgd_encoder->igd_port;
+		emgd_crtc = container_of(encoder->crtc, emgd_crtc_t, base);
+		pipe      = emgd_crtc->igd_pipe;
+
+		mode_context->kms_dispatch->kms_program_port(emgd_encoder,
+	    		IGD_DISPLAY_ENABLE);
+/*
+		port->pd_driver->set_mode(port->pd_context, pipe->timing,
+								1<<pipe->pipe_num);
+*/
+		encoder_funcs = encoder->helper_private;
+		encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+
+	}
+	/* Reset our seamless variable */
+	emgd_encoder->flags &= ~ENCODER_FLAG_SEAMLESS;
+
+	/* TODO: Add call to check_display */
+
+	EMGD_TRACE_EXIT;
+}
+
+
+
+/**
+ * emgd_encoder_mode_set
+ *
+ * This function saves the requested timings into the Port Timing Info
+ * structure.  At emgd_encoder_commit() time we should be using these
+ * timings to program the port, but currently we are using timings from
+ * the pipe.  This is fine for now, but at one point we should investigate
+ * the centering case in which the port timings may not match the pipe timings.
+ *
+ * @param encoder (IN) Encoder being prepared
+ * @param mode    (IN)
+ * @param adjusted_mode (IN)
+ *
+ * @return None
+ */
+static void emgd_encoder_mode_set(struct drm_encoder *encoder,
+		struct drm_display_mode *mode,
+		struct drm_display_mode *adjusted_mode)
+{
+	emgd_crtc_t        *emgd_crtc    = NULL;
+	emgd_encoder_t     *emgd_encoder = NULL;
+	igd_display_pipe_t *pipe         = NULL;
+	igd_display_port_t *port         = NULL;
+	pd_timing_t        *timing       = NULL;
+
+	EMGD_TRACE_ENTER;
+
+
+	emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+
+	if (!(emgd_encoder->flags & ENCODER_FLAG_SEAMLESS)) {
+		port = emgd_encoder->igd_port;
+		emgd_crtc = container_of(encoder->crtc, emgd_crtc_t, base);
+		pipe = emgd_crtc->igd_pipe;
+
+		if (pipe) {
+			timing = (pd_timing_t *)pipe->timing;
+
+			if (NULL == port->pt_info) {
+				port->pt_info = kzalloc(sizeof(igd_display_info_t), GFP_KERNEL);
+
+				if (!port->pt_info) {
+					EMGD_ERROR_EXIT("Unable to allocate pt_info.");
+					return;
+				}
+			}
+
+			port->pt_info->width        = adjusted_mode->crtc_hdisplay;
+			port->pt_info->height       = adjusted_mode->crtc_vdisplay;
+			port->pt_info->refresh      = adjusted_mode->vrefresh;
+			port->pt_info->dclk         = adjusted_mode->synth_clock;
+			port->pt_info->htotal       = adjusted_mode->crtc_htotal;
+			port->pt_info->hblank_start = adjusted_mode->crtc_hblank_start;
+			port->pt_info->hblank_end   = adjusted_mode->crtc_hblank_end;
+			port->pt_info->hsync_start  = adjusted_mode->crtc_hsync_start;
+			port->pt_info->hsync_end    = adjusted_mode->crtc_hsync_end;
+			port->pt_info->vtotal       = adjusted_mode->crtc_vtotal;
+			port->pt_info->vblank_start = adjusted_mode->crtc_vblank_start;
+			port->pt_info->vblank_end   = adjusted_mode->crtc_vblank_end;
+			port->pt_info->vsync_start  = adjusted_mode->crtc_vsync_start;
+			port->pt_info->vsync_end    = adjusted_mode->crtc_vsync_end;
+			port->pt_info->mode_number  = adjusted_mode->clock_index;
+			port->pt_info->flags        = adjusted_mode->private_flags;
+
+			port->pt_info->x_offset     = timing->x_offset;
+			port->pt_info->y_offset     = timing->y_offset;
+			port->pt_info->flags       |= IGD_DISPLAY_ENABLE;
+
+
+			EMGD_DEBUG("Calculate ELD");
+			if (calculate_eld(port, timing)) {
+				EMGD_DEBUG("Fail to calculate ELD");
+			}
+
+		} else {
+			EMGD_ERROR("Trying to set the mode without a pipe attached.");
+		}
+	}
+
+	EMGD_TRACE_EXIT;
+}
+
+
+
+/**
+ * emgd_encoder_destroy
+ *
+ * Frees the resources allocated for this encoder during "create_encoder()"
+ *
+ * @param encoder (IN) Encoder to be freed
+ *
+ * @return None
+ */
+static void emgd_encoder_destroy(struct drm_encoder *encoder)
+{
+	emgd_encoder_t *emgd_encoder;
+
+	EMGD_TRACE_ENTER;
+	emgd_encoder = container_of(encoder, emgd_encoder_t, base);
+
+	drm_encoder_cleanup(encoder);
+
+	kfree(emgd_encoder);
+
+	EMGD_TRACE_EXIT;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_fb.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_fb.c
new file mode 100644
index 0000000..6e00b27
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_fb.c
@@ -0,0 +1,1413 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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 <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 *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 *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,
+};
+
+
+
+/*
+ * 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 *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->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 *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/drivers/gpu/drm/emgd/emgd/drm/emgd_fbcon.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_fbcon.c
new file mode 100644
index 0000000..5132d33
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_fbcon.c
@@ -0,0 +1,805 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_fbcon.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:
+ *  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"
+
+
+/*------------------------------------------------------------------------------
+ * 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 *mode_cmd,
+			unsigned long handle);
+
+
+/* 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->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  mode_cmd;
+
+	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;
+
+	/* 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.handle = EMGD_INITIAL_FRAMEBUFFER;
+	mode_cmd.pitch  = priv->initfb_info.screen_pitch;
+	mode_cmd.width  = priv->initfb_info.width;
+	mode_cmd.height = priv->initfb_info.height;
+	mode_cmd.bpp    = IGD_PF_BPP(priv->initfb_info.pixel_format);
+	mode_cmd.depth  = mode_cmd.bpp;  /* Ok for 32bpp, may not work for 16bpp */
+
+	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;
+}
+
+
+
+static int emgd_fbcon_set_par(struct fb_info *info)
+{
+	int ret = 0;
+
+	EMGD_TRACE_ENTER;
+
+	// set mode here:  crtc->set_config
+    // look at drm_fb_helper_set_par for reference
+
+
+	EMGD_TRACE_EXIT;
+
+	return ret;
+}
+
+
+
+static int emgd_fbcon_setcolreg(unsigned int regno,
+		unsigned int red, unsigned int green, unsigned int blue,
+		unsigned int transp, struct fb_info *info)
+{
+	EMGD_TRACE_ENTER;
+
+	EMGD_DEBUG("STUBED emgd_fbcon_setcolreg");
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+
+
+static int emgd_fbcon_pan_display(struct fb_var_screeninfo *var,
+		struct fb_info *info)
+{
+	int ret = 0;
+
+	EMGD_TRACE_ENTER;
+
+
+
+	EMGD_TRACE_EXIT;
+	return ret;
+}
+
+
+
+/*
+ * Currently, we are using the device indpendent DRM functions
+ * for these.  If we need to do special processing, then uncomment
+ * these functions and hook them into the function table.
+ */
+static int emgd_fbcon_blank(int blank, struct fb_info *info)
+{
+	int ret = 0;
+	struct drm_device *dev;
+	struct drm_crtc *crtc = NULL;
+	struct drm_encoder *encoder = NULL;
+	struct drm_encoder_helper_funcs *encoder_funcs;
+	emgd_fbdev_t *emgd_fbdev;
+
+	EMGD_TRACE_ENTER;
+
+	emgd_fbdev = info->par;
+	dev	       = emgd_fbdev->priv->ddev;
+
+	switch(blank) {
+	case FB_BLANK_UNBLANK:
+		EMGD_DEBUG("Turn on Display");
+
+		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+
+			((struct drm_crtc_helper_funcs *)crtc->helper_private)->dpms(crtc,
+				DRM_MODE_DPMS_ON);
+
+			list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+				if(encoder->crtc == crtc) {
+					encoder_funcs = encoder->helper_private;
+					encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+				}
+			}
+		}
+		break;
+	case FB_BLANK_NORMAL:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_POWERDOWN:
+		EMGD_DEBUG("Turn off Display");
+
+		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+			list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+				if(encoder->crtc == crtc) {
+					encoder_funcs = encoder->helper_private;
+					encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
+				}
+			}
+
+			((struct drm_crtc_helper_funcs *)crtc->helper_private)->dpms(crtc,
+				DRM_MODE_DPMS_OFF);
+		}
+		break;
+	default:
+		EMGD_DEBUG("ERROR: Incorrect FB_BLANK value passed");
+		break;
+	}
+
+	EMGD_TRACE_EXIT;
+
+	return ret;
+}
+
+
+
+/*
+ * emgd_fbcon_initial_config
+ *
+ * Uses configurations in config_drm to set the start-up configuration.
+ * We will not support configurations that require more than one framebuffer
+ * at DRM boot time.  The fallback configuration is SINGLE.
+ *
+ * @param emgd_fbdev (IN) Framebuffer device to initialize
+ *
+ * @return 0 on success, an error code otherwise
+ */
+int emgd_fbcon_initial_config(emgd_fbdev_t *emgd_fbdev)
+{
+	int                    err;
+	unsigned long         *dc_assigned;
+	igd_context_t         *context;
+	unsigned short         port_number;
+	emgd_crtc_t           *emgd_crtc;
+	struct drm_crtc       *crtc         = NULL;
+	igd_display_context_t *primary      = NULL, *secondary = NULL;
+	bool                   mode_set_ret = FALSE;
+	struct drm_device     *dev          = emgd_fbdev->priv->ddev;
+
+	struct drm_display_mode primary_mode, secondary_mode;
+
+	EMGD_TRACE_ENTER;
+
+
+	context = ((drm_emgd_priv_t *)dev->dev_private)->context;
+
+
+	/* Basic error checking.  SINGLE is the fallback configuration */
+	if( IGD_DISPLAY_CONFIG_CLONE  != config_drm.dc &&
+		IGD_DISPLAY_CONFIG_SINGLE != config_drm.dc ) {
+		config_drm.dc = IGD_DISPLAY_CONFIG_SINGLE;
+	}
+
+
+	/*******************************************************
+	 * Allocate DSP for the desired DC.  This is to make sure the
+	 * display context is valid for subsequent operations.  The
+	 * dc_assigned coming out will contain port info in addition to
+	 * display configuration.
+	 ******************************************************/
+	/* Query for the best DC that matches the request */
+	err = context->dispatch.query_dc(context, config_drm.dc,
+								&dc_assigned, IGD_QUERY_DC_INIT);
+	if (err) {
+		EMGD_ERROR_EXIT("Cannot initialize the display as requested.\n"
+				"The query_dc() function returned %d.", err);
+		return -IGD_ERROR_INVAL;
+	}
+
+	emgd_fbdev->priv->dc = *dc_assigned;
+
+
+	/* Allocate and initialize igd_display_context */
+	err = context->mod_dispatch.dsp_alloc(context, *dc_assigned, 0);
+	if (err) {
+		EMGD_ERROR_EXIT("Cannot initialize display context.\n"
+			"The dsp_alloc() function returned %d.", err);
+		return -IGD_ERROR_INVAL;
+	}
+
+	/* Initialize pipe->owner for PRIMARY and SECONDARY */
+	port_number = IGD_DC_PRIMARY(*dc_assigned);
+
+	primary = context->mod_dispatch.dsp_display_list[port_number];
+	PIPE(primary)->owner = primary;
+
+	if (IGD_DC_SECONDARY(*dc_assigned)) {
+		port_number = IGD_DC_SECONDARY(*dc_assigned);
+		secondary = context->mod_dispatch.dsp_display_list[port_number];
+		PIPE(secondary)->owner = secondary;
+	}
+
+
+
+	/*******************************************************
+	 * Allocate framebuffer
+	 ******************************************************/
+	if (0 == (err = alloc_initial_fb(emgd_fbdev))) {
+
+		/* Attach the frame buffer to the CRTC(s)  */
+		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+			emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+
+			if (PIPE(primary) == emgd_crtc->igd_pipe) {
+				crtc->fb = &emgd_fbdev->emgd_fb->base;
+			}
+
+			/* Attach frame buffer to the secondary CRTC, if necessary */
+			if (IGD_DC_SECONDARY(*dc_assigned) &&
+				PIPE(secondary) == emgd_crtc->igd_pipe) {
+				crtc->fb = &emgd_fbdev->emgd_fb->base;
+			}
+		}
+
+
+		err = register_framebuffer(emgd_fbdev->priv->fbdev);
+
+		EMGD_DEBUG("fb%d: %s framebuffer device",
+			emgd_fbdev->priv->fbdev->node,
+			emgd_fbdev->priv->fbdev->fix.id);
+	}
+
+
+	/*******************************************************
+	 * Set Mode for Primary
+	 ******************************************************/
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+
+		if (PIPE(primary) == emgd_crtc->igd_pipe) {
+
+			memset(&primary_mode, 0, sizeof(primary_mode));
+			primary_mode.crtc_hdisplay = config_drm.width;
+			primary_mode.crtc_vdisplay = config_drm.height;
+			primary_mode.vrefresh      = config_drm.refresh;
+
+			mode_set_ret = drm_crtc_helper_set_mode(crtc,
+								&primary_mode,
+								0, 0,
+								NULL);
+			break;
+		}
+	}
+
+	if (FALSE == mode_set_ret) {
+		EMGD_ERROR_EXIT("Failed to set mode on primary CRTC.  Abort.");
+		return -IGD_ERROR_INVAL;
+	}
+
+
+	/*******************************************************
+	 * Set Mode for Secondary, if necessary
+	 ******************************************************/
+	if (IGD_DC_SECONDARY(*dc_assigned)) {
+
+		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+			emgd_crtc = container_of(crtc, emgd_crtc_t, base);
+
+			if (PIPE(secondary) == emgd_crtc->igd_pipe) {
+
+				memset(&secondary_mode, 0, sizeof(secondary_mode));
+				secondary_mode.crtc_hdisplay = config_drm.width;
+				secondary_mode.crtc_vdisplay = config_drm.height;
+				secondary_mode.vrefresh      = config_drm.refresh;
+
+				mode_set_ret = drm_crtc_helper_set_mode(crtc,
+								&secondary_mode,
+								0, 0,
+								NULL);
+								break;
+			}
+		}
+
+	}
+
+	if (FALSE == mode_set_ret) {
+		EMGD_ERROR_EXIT("Failed to set mode on secondary CRTC.  Abort.");
+		return -IGD_ERROR_INVAL;
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+	return 0;
+}
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_interface.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_interface.c
new file mode 100644
index 0000000..9a5a4bc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_interface.c
@@ -0,0 +1,2730 @@
+/*-----------------------------------------------------------------------------
+ * Filename: emgd_interface.c
+ * $Revision: 1.190 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF 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);
+			break;
+		default:
+			break;
+		}
+		break;
+	case CMD_VIDEO_CREATE_CONTEXT:
+		switch (drm_data->engine) {
+		case PSB_ENGINE_VIDEO:
+			drm_data->rtn = msvdx_create_context(context);
+			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 = msvdx_flush_tlb(context);
+			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/drivers/gpu/drm/emgd/emgd/drm/emgd_mmap.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_mmap.c
new file mode 100644
index 0000000..c1d13a2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_mmap.c
@@ -0,0 +1,186 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_mmap.c
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Memory mapping functions.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.gart
+
+#include <linux/mm.h>
+#include <drm_emgd_private.h>
+#include <emgd_drv.h>
+#include <emgd_drm.h>
+#include <memory.h>
+#include <memlist.h>
+#include <io.h>
+
+/*
+ * Bottom 256MB reserved for display
+ */
+#define DRM_PSB_FILE_PAGE_OFFSET (0x10000000UL >> PAGE_SHIFT)
+
+extern gmm_chunk_t *gmm_get_chunk(igd_context_t *context,
+		unsigned long vm_pgoff);
+extern int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma);
+
+static int emgd_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
+static void emgd_vm_open(struct vm_area_struct *vma);
+static void emgd_vm_close(struct vm_area_struct *vma);
+
+static struct vm_operations_struct emgd_vm_ops = {
+	.fault = emgd_vm_fault,
+	.open = emgd_vm_open,
+	.close = emgd_vm_close
+};
+
+/*
+ * Create a virtual address mapping for physical pages of memory.
+ *
+ * This needs to handle requrests for both the EMGD display driver
+ * and the IMG 2D/3D drivers.
+ *
+ * If the page offset falls below the 256MB limit for display,
+ * then map display memory. If above, route to the IMG handler.
+ */
+int emgd_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct drm_file *file_priv;
+	drm_emgd_priv_t *emgd_priv;
+	gmm_chunk_t *chunk;
+	unsigned long offset;
+
+	/*
+	 * re-direct offsets beyond the 256MB display range to PVRMMap
+	 */
+	if (vma->vm_pgoff > DRM_PSB_FILE_PAGE_OFFSET) {
+		EMGD_DEBUG("emgd_mmap: Calling PVRMMap().");
+		return PVRMMap(filp, vma);
+	}
+
+	file_priv = (struct drm_file *) filp->private_data;
+	emgd_priv = (drm_emgd_priv_t *)file_priv->minor->dev->dev_private;
+	offset = vma->vm_pgoff << PAGE_SHIFT;
+
+	/*
+	 * Look up the buffer in the gmm chunk list based on offset
+	 * and size.
+	 */
+	/* chunk = emgd_priv->context->dispatch->gmm_get_chunk(vma->vm_pgoff);*/
+	chunk = gmm_get_chunk(emgd_priv->context, offset);
+	if (chunk == NULL) {
+		printk(KERN_ERR "emgd_mmap: Failed to find memory at 0x%lx.", offset);
+	}
+
+	/*
+	 * Fill in the vma
+	 */
+	vma->vm_ops = &emgd_vm_ops;
+	vma->vm_private_data = chunk;
+	vma->vm_flags |= VM_RESERVED | VM_IO | VM_MIXEDMAP | VM_DONTEXPAND;
+	pgprot_val(vma->vm_page_prot) =
+		pgprot_val(vma->vm_page_prot) | _PAGE_CACHE_UC_MINUS;
+
+	return 0;
+}
+
+
+static int emgd_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	unsigned long offset;
+	unsigned long pg_offset;
+	gmm_chunk_t *chunk;
+	struct page *page;
+
+	offset = (unsigned long)vmf->virtual_address - vma->vm_start;
+	pg_offset = offset >> PAGE_SHIFT;
+
+	chunk = (gmm_chunk_t *)vma->vm_private_data;
+
+	if (chunk == NULL) {
+		printk(KERN_ERR "emgd_vm_fault: Chunk is NULL.\n");
+		vmf->page = NULL;
+		return VM_FAULT_SIGBUS;
+	}
+
+	if (pg_offset > chunk->gtt_mem->page_count) {
+		printk(KERN_ERR "emgd_vm_fault: page offet (%lu) > page count (%d)\n",
+				pg_offset, chunk->gtt_mem->page_count);
+		return VM_FAULT_SIGBUS;
+	}
+
+	page = chunk->gtt_mem->pages[pg_offset];
+	get_page(page);
+	vmf->page = page;
+
+	return 0;
+}
+
+/*
+ * Increase the refrence count on the memory object
+ */
+static void emgd_vm_open(struct vm_area_struct *vma)
+{
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->minor->dev;
+
+
+	/*
+	 * Does the DRM really need to keep track of the count if we're managing
+	 * everything?
+	 */
+	atomic_inc(&dev->vma_count);
+
+	/*
+	 * DRM code maintains a list of vma's and when open is
+	 * called, the vma is added to the list.
+	 */
+
+}
+
+/*
+ * Decrease the reference count on the memory object and
+ * remove the refrence to the memory object.
+ */
+static void emgd_vm_close(struct vm_area_struct *vma)
+{
+	struct drm_file *priv = vma->vm_file->private_data;
+	struct drm_device *dev = priv->minor->dev;
+
+	/*
+	 * Does the DRM really need to keep track of the count if we're managing
+	 * everything?
+	 */
+	atomic_dec(&dev->vma_count);
+
+	/*
+	 * DRM code maintains a list of vma's and when close is
+	 * called, the vma is removed to the list.
+	 */
+
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/drm/emgd_test_pvrsrv.c b/drivers/gpu/drm/emgd/emgd/drm/emgd_test_pvrsrv.c
new file mode 100644
index 0000000..6ba4567
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/emgd_test_pvrsrv.c
@@ -0,0 +1,1365 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_test_pvrsrv.c
+ * $Revision: 1.23 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file implements an ioctl devoted to the "ult/drmtest_surface.c" test.
+ *  It tests the 3rd-Party Display Driver (and as such, it tests some of the
+ *  PVR services) within kernel-space.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.oal
+
+#include "drmP.h"
+#include "drm.h"
+
+#include "drm_emgd_private.h"
+#include "emgd_drm.h"
+#include "emgd_drv.h"
+#include "memory.h"
+
+#include "module_init.h"
+#include "mode_dispatch.h"
+#include "ovl_dispatch.h"
+#include "ovl_virt.h"
+#include "msvdx.h"
+
+#include "memmap.h"
+#include "sched.h"
+
+#include "services.h"
+#include "perproc.h"
+#include "pvr_bridge_km.h"
+#include "syscommon.h"
+#include "pvr_drm.h"
+/* Pull in whether HAL & 3rd-party display driver (3DD) should use interrupts */
+#include "emgd_shared.h"
+
+
+
+/* Note: The following "TEST_ERROR" macro is only for this function.  It prints
+ * the message to the kernel log, and it formats and inserts the same message
+ * into the drm_data->rtn_msg, so that the user-space code can print it.
+ */
+#define TEST_ERROR(format, arg...) \
+	printk(KERN_ERR format, ##arg);\
+	snprintf(drm_data->rtn_msg, 1024, format, ##arg);
+
+
+#define NUM_FRONT_BUFFERS 1
+#define NUM_BACK_BUFFERS 2
+#define NUM_BUFFERS (NUM_FRONT_BUFFERS + NUM_BACK_BUFFERS)
+
+
+#define DEVICE1 0
+#define DEVICE2 1
+
+
+/* Common colors: */
+#define BLACK   0xff000000
+#define WHITE   0xffffffff
+#define RED     0xffff0000
+#define GREEN   0xff00ff00
+#define BLUE    0xff0000ff
+#define CYAN    0xff00ffff
+#define YELLOW  0xffffff00
+#define MAGENTA 0xffff00ff
+
+
+/*
+ * Note: Am using the following global variables as a sort-of "poor man's OO"
+ * class members:
+ */
+static emgd_drm_test_pvrsrv_t *drm_data;
+static drm_emgd_priv_t *priv;
+
+static PVRSRV_PER_PROCESS_DATA *pp_data = NULL;
+static void *sgx_cookie = NULL;
+
+static void *dev_mem_context = NULL;
+static unsigned long heap_count = 0;
+static IMG_BOOL mem_created, dummy, mem_destroyed;
+
+static unsigned long dev_ids[2] = {0, 0};
+static void *dev_handle[2] = {NULL, NULL};
+static DISPLAY_INFO display_info;
+static DISPLAY_FORMAT *pf = NULL, *pixel_formats = NULL;
+static unsigned long num_dims = 0;
+static DISPLAY_DIMS *dim = NULL, *dimensions = NULL;
+
+static void *sys_buffer = NULL;
+static PVRSRV_KERNEL_MEM_INFO *sysbuf_mem_info = NULL;
+static void *sysbuf_map_info = NULL;
+
+#if 0
+static unsigned long fb_offset = 0;
+#endif
+static unsigned long mapped_fb_addr = 0;
+
+static DISPLAY_SURF_ATTRIBUTES	dst_surf_attrib;
+static DISPLAY_SURF_ATTRIBUTES	src_surf_attrib;
+static void *swap_chain = NULL;
+static unsigned long swap_chain_id = 0;
+
+static void *buffers[NUM_BUFFERS] = {NULL, NULL, NULL};
+static PVRSRV_KERNEL_MEM_INFO *buffers_mem_info[NUM_BUFFERS] = {NULL, NULL, NULL};
+static void *buffers_map_info[NUM_BUFFERS] = {NULL, NULL, NULL};
+
+
+
+
+
+/*!
+ * Initialize PVR services (including the 3DD), and get general info:
+ */
+static void init_pvrsrv(void)
+{
+	int i;
+	unsigned long num = 10;
+	PVRSRV_ERROR err;
+
+	EMGD_TRACE_ENTER;
+
+
+	if (!drm_data->rtn) {
+		/* This is similar to PVRSRVConnect(): */
+		EMGD_DEBUG("Calling PVRSRVPerProcessDataConnect()");
+		err = PVRSRVPerProcessDataConnect(/*Use a dummy PID*/ 200);
+		EMGD_DEBUG("Calling PVRSRVPerProcessData()");
+		pp_data = PVRSRVPerProcessData(/*Use a dummy PID*/ 200);
+		EMGD_DEBUG("  TEST: pp_data = 0x%p", pp_data);
+		if ((err != PVRSRV_OK) || (NULL == pp_data)) {
+			TEST_ERROR("[EMGD] can not find per-process data\n");
+			drm_data->rtn = -1;
+		}
+	}
+	if (!drm_data->rtn) {
+		/* Enumerate the devices and acquire the SGX device: */
+		PVRSRV_DEVICE_IDENTIFIER dev_id_list[10];
+
+		EMGD_DEBUG("Calling PVRSRVEnumerateDevicesKM()");
+		err = PVRSRVEnumerateDevicesKM(&num, dev_id_list);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVEnumerateDevicesKM() returned %d\n", err);
+			drm_data->rtn = -1;
+		} else {
+			EMGD_DEBUG("  PVRSRVEnumerateDevicesKM() found %ld devices", num);
+			for (i = 0 ; i < num ; i++) {
+				PVRSRV_DEVICE_IDENTIFIER *id = dev_id_list + i;
+				unsigned long cookie = 0;
+				EMGD_DEBUG("    Device %d has type %d, class %d & index %ld", i,
+					id->eDeviceType, id->eDeviceClass, id->ui32DeviceIndex);
+				if (PVRSRV_DEVICE_TYPE_EXT != id->eDeviceType) {
+					/* Call PVRSRVAcquireDeviceDataKM(): */
+					EMGD_DEBUG("Calling PVRSRVAcquireDeviceDataKM()");
+					err = PVRSRVAcquireDeviceDataKM(id->ui32DeviceIndex,
+						PVRSRV_DEVICE_TYPE_UNKNOWN, (void *) &cookie);
+					if (err != PVRSRV_OK) {
+						TEST_ERROR("[EMGD] PVRSRVAcquireDeviceDataKM() "
+							"returned %d\n", err);
+						drm_data->rtn = -1;
+						break;
+					}
+					if (PVRSRV_DEVICE_TYPE_SGX == id->eDeviceType) {
+						EMGD_DEBUG("  Found cookie = 0x%lx", cookie);
+						/* Save this away for later: */
+						sgx_cookie = (void *) cookie;
+					}
+				}
+			}
+		}
+	}
+	if (!drm_data->rtn) {
+		/* Enumerate the display class devices to be able to find the 3DD: */
+		EMGD_DEBUG("Calling PVRSRVEnumerateDCKM()");
+EMGD_DEBUG("dev_ids=0x%p", dev_ids);
+		err = PVRSRVEnumerateDCKM(PVRSRV_DEVICE_CLASS_DISPLAY,
+			&num, dev_ids);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVEnumerateDCKM() returned %d\n", err);
+			drm_data->rtn = -1;
+		} else {
+			/* Find the 3DD: */
+			EMGD_DEBUG("  PVRSRVEnumerateDCKM() found %ld devices", num);
+			for (i = 0 ; i < num ; i++) {
+				EMGD_DEBUG("    device %d has ID %ld", i, dev_ids[i]);
+			}
+			if (0 == dev_ids[0]) {
+				TEST_ERROR("[EMGD] Did not find 3rd-party display driver ID\n");
+				drm_data->rtn = -1;
+			}
+		}
+	}
+	if (!drm_data->rtn) {
+		/* Call PVRSRVCreateDeviceMemContextKM(): */
+		PVRSRV_HEAP_INFO heap_info[PVRSRV_MAX_CLIENT_HEAPS];
+
+		EMGD_DEBUG("Calling PVRSRVCreateDeviceMemContextKM()");
+		err = PVRSRVCreateDeviceMemContextKM(sgx_cookie, pp_data,
+			&dev_mem_context, &heap_count, heap_info, &mem_created, &dummy);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVCreateDeviceMemContextKM() "
+				"returned %d\n", err);
+			drm_data->rtn = -1;
+		}
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+} /* init_pvrsrv() */
+
+
+
+
+
+/*!
+ * IOCTL to allow a ult test ("drmtest_surface.c") to test our 3rd-party
+ * display driver (3DD) without the need for the user-mode IMG service code.
+ */
+static void deinit_pvrsrv(void)
+{
+	PVRSRV_ERROR err;
+
+	EMGD_TRACE_ENTER;
+
+
+	if (NULL != dev_mem_context) {
+		EMGD_DEBUG("Calling PVRSRVDestroyDeviceMemContextKM()");
+		err = PVRSRVDestroyDeviceMemContextKM(sgx_cookie, dev_mem_context,
+			&mem_destroyed);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVDestroyDeviceMemContext() "
+				"returned %d\n", err);
+			drm_data->rtn = -1;
+		}
+	}
+
+	if (NULL != pp_data) {
+		EMGD_DEBUG("Calling PVRSRVPerProcessDataDisconnect()");
+		PVRSRVPerProcessDataDisconnect(/*Use a dummy PID*/ 200);
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+} /* deinit_pvrsrv() */
+
+
+
+
+
+/*!
+ * Initialize PVR services (including the 3DD), and get general info:
+ */
+static void open_device(int which_device)
+{
+	int i;
+	unsigned long num = 10;
+	PVRSRV_ERROR err;
+
+	EMGD_TRACE_ENTER;
+
+
+	if (!drm_data->rtn) {
+		/* Finally, open a connection to the 3DD: */
+		EMGD_DEBUG("Calling PVRSRVOpenDCDeviceKM()");
+		err = PVRSRVOpenDCDeviceKM(pp_data, dev_ids[which_device], sgx_cookie,
+			&dev_handle[which_device]);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVOpenDCDeviceKM() returned %d\n", err);
+			drm_data->rtn = -1;
+		}
+		if (NULL == dev_handle[which_device]) {
+			TEST_ERROR("[EMGD] PVRSRVOpenDCDeviceKM() returned NULL handle\n");
+			drm_data->rtn = -1;
+		}
+	}
+	if (!drm_data->rtn) {
+		/* Get information about the display: */
+		EMGD_DEBUG("Calling PVRSRVGetDCInfoKM()");
+		err = PVRSRVGetDCInfoKM(dev_handle[which_device], &display_info);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVGetDCInfoKM() returned %d\n", err);
+			drm_data->rtn = -1;
+		} else {
+			EMGD_DEBUG("PVRSRVGetDCInfoKM() returned the following info:");
+			EMGD_DEBUG("  name = \"%s\"", display_info.szDisplayName);
+			EMGD_DEBUG("  MaxSwapChains = %lu", display_info.ui32MaxSwapChains);
+			EMGD_DEBUG("  MaxSwapChainBuffers = %lu",
+				display_info.ui32MaxSwapChainBuffers);
+			EMGD_DEBUG("  MinSwapInterval = %lu",
+				display_info.ui32MinSwapInterval);
+			EMGD_DEBUG("  MaxSwapInterval = %lu",
+				display_info.ui32MaxSwapInterval);
+		}
+	}
+	if (!drm_data->rtn) {
+		/* Get the the number of pixel formats: */
+		EMGD_DEBUG("Calling PVRSRVEnumDCFormatsKM()");
+		err = PVRSRVEnumDCFormatsKM(dev_handle[which_device], &num, NULL);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVEnumDCFormatsKM() returned %d\n",err);
+			drm_data->rtn = -1;
+		}
+		if (0 == num) {
+			TEST_ERROR("[EMGD] PVRSRVEnumDCFormatsKM() says that there "
+				"are %lu pixel formats\n", num);
+			drm_data->rtn = -1;
+		}
+	}
+	if (!drm_data->rtn) {
+		/* Get the pixel formats: */
+		EMGD_DEBUG("Allocating space for %lu pixel formats", num);
+		pixel_formats = OS_ALLOC(sizeof(DISPLAY_FORMAT) * num);
+		EMGD_DEBUG("Calling PVRSRVEnumDCFormatsKM()");
+		err = PVRSRVEnumDCFormatsKM(dev_handle[which_device], &num,
+			pixel_formats);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVEnumDCFormatsKM() returned %d\n", err);
+			drm_data->rtn = -1;
+		} else {
+			pf = pixel_formats;
+			for (i = 0 ; i < num ; i++) {
+				EMGD_DEBUG("  pixel format %d is %d", i, pf->pixelformat);
+				pf++;
+			}
+			/* Save the first pixel format (the one being used): */
+			pf = pixel_formats;
+		}
+	}
+
+
+	if (!drm_data->rtn) {
+		/* Get the number of display dimensions: */
+		EMGD_DEBUG("Calling PVRSRVEnumDCDimsKM()");
+		err = PVRSRVEnumDCDimsKM(dev_handle[which_device], pf, &num_dims, NULL);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVEnumDCDimsKM() returned %d\n", err);
+			drm_data->rtn = -1;
+		}
+		if (0 == num_dims) {
+			TEST_ERROR("[EMGD] PVRSRVEnumDCDimsKM() says that there "
+				"are %lu dimensions\n", num_dims);
+			drm_data->rtn = -1;
+		}
+	}
+	if (!drm_data->rtn) {
+		/* Get the display dimensions: */
+		EMGD_DEBUG("Allocating space for %lu dimensions", num_dims);
+		dimensions = OS_ALLOC(sizeof(DISPLAY_DIMS) * num_dims);
+		EMGD_DEBUG("Calling PVRSRVEnumDCDimsKM()");
+		err = PVRSRVEnumDCDimsKM(dev_handle[which_device], pf, &num_dims,
+			dimensions);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVEnumDCDimsKM() returned %d\n", err);
+			drm_data->rtn = -1;
+		} else {
+			dim = dimensions;
+			for (i = 0 ; i < num_dims ; i++) {
+				EMGD_DEBUG("  dimension %d is width = %lu, height = %lu, "
+					"stride = %lu", i, dim->ui32Width, dim->ui32Height,
+					dim->ui32ByteStride);
+				dim++;
+			}
+			/* Save the first dimension (the one being used): */
+			dim = dimensions;
+		}
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+} /* open_device() */
+
+
+
+
+
+/*!
+ * IOCTL to allow a ult test ("drmtest_surface.c") to test our 3rd-party
+ * display driver (3DD) without the need for the user-mode IMG service code.
+ */
+static void close_device(int which_device)
+{
+	PVRSRV_ERROR err;
+
+	EMGD_TRACE_ENTER;
+
+
+	if (NULL != sysbuf_mem_info) {
+		EMGD_DEBUG("Calling PVRSRVUnmapDeviceClassMemoryKM()");
+		err = PVRSRVUnmapDeviceClassMemoryKM(sysbuf_mem_info);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVUnmapDeviceClassMemoryKM() "
+				"returned %d\n", err);
+			drm_data->rtn = -1;
+		}
+	}
+	if (NULL != dimensions) {
+		OS_FREE(dimensions);
+	}
+	if (NULL != pixel_formats) {
+		OS_FREE(pixel_formats);
+	}
+	if (NULL != dev_handle[which_device]) {
+		EMGD_DEBUG("Calling PVRSRVCloseDCDeviceKM()");
+		err = PVRSRVCloseDCDeviceKM(dev_handle[which_device], dummy);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVCloseDCDeviceKM() returned %d\n", err);
+			drm_data->rtn = -1;
+		}
+	}
+
+	if (NULL != dev_mem_context) {
+		EMGD_DEBUG("Calling PVRSRVDestroyDeviceMemContextKM()");
+		err = PVRSRVDestroyDeviceMemContextKM(sgx_cookie, dev_mem_context,
+			&mem_destroyed);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVDestroyDeviceMemContext() "
+				"returned %d\n", err);
+			drm_data->rtn = -1;
+		}
+	}
+
+	if (NULL != pp_data) {
+		EMGD_DEBUG("Calling PVRSRVPerProcessDataDisconnect()");
+		PVRSRVPerProcessDataDisconnect(/*Use a dummy PID*/ 200);
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+} /* close_device() */
+
+
+
+
+/*!
+ * Maps the "system buffer" and paints it a solid color.
+ */
+static void map_and_paint_fb(int which_device, unsigned long color)
+{
+	int i;
+	PVRSRV_ERROR err;
+
+	EMGD_TRACE_ENTER;
+
+
+	/* Get a handle to the primary surface (a.k.a. "system buffer"): */
+	EMGD_DEBUG("Calling PVRSRVGetDCSystemBufferKM()");
+	err = PVRSRVGetDCSystemBufferKM(dev_handle[which_device], &sys_buffer);
+	if (err != PVRSRV_OK) {
+		TEST_ERROR("[EMGD] PVRSRVGetDCSystemBufferKM() returned %d\n", err);
+		drm_data->rtn = -1;
+	} else if (NULL == sys_buffer) {
+		TEST_ERROR("[EMGD] PVRSRVGetDCSystemBufferKM() returned a "
+			"NULL handle to the system buffer\n");
+		drm_data->rtn = -1;
+	}
+
+	if (!drm_data->rtn) {
+		/* Map the memory of the "system buffer": */
+		EMGD_DEBUG("Calling PVRSRVMapDeviceClassMemoryKM()");
+		err = PVRSRVMapDeviceClassMemoryKM(pp_data, dev_mem_context,
+			sys_buffer, &sysbuf_mem_info, &sysbuf_map_info);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVMapDeviceClassMemoryKM() "
+				"returned %d\n", err);
+			drm_data->rtn = -1;
+		} else if (NULL == sysbuf_mem_info) {
+			TEST_ERROR("[EMGD] PVRSRVMapDeviceClassMemoryKM() returned a "
+				"NULL pointer to the system buffer's PVRSRV_KERNEL_MEM_INFO\n");
+			drm_data->rtn = -1;
+		} else {
+			EMGD_DEBUG("  pvLinAddrKM = 0x%p", sysbuf_mem_info->pvLinAddrKM);
+			EMGD_DEBUG("  sDevVAddr = 0x%lx",sysbuf_mem_info->sDevVAddr.uiAddr);
+			EMGD_DEBUG("  ui32Flags = 0x%lx", sysbuf_mem_info->ui32Flags);
+			EMGD_DEBUG("  ui32AllocSize = %lu = 0x%lx",
+				sysbuf_mem_info->ui32AllocSize, sysbuf_mem_info->ui32AllocSize);
+			EMGD_DEBUG("  sMemBlk.sDevVirtAddr = %lu = 0x%lx",
+				sysbuf_mem_info->sMemBlk.sDevVirtAddr.uiAddr,
+				sysbuf_mem_info->sMemBlk.sDevVirtAddr.uiAddr);
+			EMGD_DEBUG("  sMemBlk.psIntSysPAddr = 0x%p",
+				sysbuf_mem_info->sMemBlk.psIntSysPAddr);
+			EMGD_DEBUG("  pvSysBackupBuffer = 0x%p",
+				sysbuf_mem_info->pvSysBackupBuffer);
+			EMGD_DEBUG("  ui32RefCount = %lu", sysbuf_mem_info->ui32RefCount);
+			EMGD_DEBUG("  bPendingFree = 0x%d", sysbuf_mem_info->bPendingFree);
+			EMGD_DEBUG("  psKernelSyncInfo = 0x%p",
+				sysbuf_mem_info->psKernelSyncInfo);
+		}
+	}
+	if (!drm_data->rtn) {
+		/* Draw the "system buffer" the desired color: */
+		mapped_fb_addr = (unsigned long) (sysbuf_mem_info->pvLinAddrKM);
+		if (0 == mapped_fb_addr) {
+			TEST_ERROR("[EMGD] Failed to map the framebuffer\n");
+			drm_data->rtn = -1;
+		} else {
+			unsigned long *fb = (unsigned long *) (mapped_fb_addr);
+			unsigned int pixels = sysbuf_mem_info->ui32AllocSize / 4;
+			EMGD_DEBUG("  Mapped %luMB @ virtual addr= 0x%lx",
+				sysbuf_mem_info->ui32AllocSize/(1024*1024), mapped_fb_addr);
+			EMGD_DEBUG("     About to write to addr = 0x%p", fb);
+			EMGD_DEBUG("     About to write %d (0x%x) pixels",
+				pixels, pixels);
+			for (i = 0 ; i < pixels ; i++) {
+#if 0
+				if (0 == (i % 1024)) {
+					printk("row %3d: fb=0x%p\n", (i / 1024), fb);
+				}
+#endif
+				*fb++ = color;
+			}
+		}
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+} /* map_and_paint_fb() */
+
+
+
+
+/*!
+ * Creates a swap chain, maps the buffers, and paints each a solid color.
+ */
+static void create_swap_chain(int which_device, int which_dimension,
+	unsigned long fb_color,
+	unsigned long bb1_color,
+	unsigned long bb2_color)
+{
+	int i, j;
+	unsigned long num = 10;
+	PVRSRV_ERROR err;
+
+	EMGD_TRACE_ENTER;
+
+
+	/**************************************************************************
+	 *
+	 * Create a swap chain, draw green to one back buffer and red to the
+	 * other; and then flip between the frame buffer and the 2 back buffers:
+	 *
+	 **************************************************************************/
+	if (!drm_data->rtn) {
+		/* Create a swap chain: */
+		dst_surf_attrib.pixelformat = pf->pixelformat;
+		dst_surf_attrib.sDims = dimensions[which_dimension];
+		src_surf_attrib.pixelformat = pf->pixelformat;
+		src_surf_attrib.sDims = dimensions[which_dimension];
+		EMGD_DEBUG("Calling PVRSRVCreateDCSwapChainKM()");
+		err = PVRSRVCreateDCSwapChainKM(pp_data, dev_handle[which_device], 0,
+			&dst_surf_attrib, &src_surf_attrib, NUM_BUFFERS, 0, &swap_chain,
+			&swap_chain_id);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVCreateDCSwapChainKM() returned %d\n", err);
+			drm_data->rtn = -1;
+		} else {
+			EMGD_DEBUG("PVRSRVCreateDCSwapChainKM() returned swap_chain=0x%p, "
+				"ID=%lu", swap_chain, swap_chain_id);
+		}
+	}
+	if (!drm_data->rtn) {
+		/* Get the DC Buffers: */
+		num = NUM_BUFFERS;
+		EMGD_DEBUG("Calling PVRSRVGetDCBuffersKM()");
+		err = PVRSRVGetDCBuffersKM(dev_handle[which_device], swap_chain, &num,
+			buffers);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVGetDCBuffersKM() returned %d\n", err);
+			drm_data->rtn = -1;
+		} else if (NUM_BUFFERS != num) {
+			TEST_ERROR("[EMGD] PVRSRVGetDCBuffersKM() changed number of "
+				"buffers to %lu\n", num);
+			drm_data->rtn = -1;
+		} else {
+			EMGD_DEBUG("PVRSRVGetDCBuffersKM() returned buffers: 0x%p, 0x%p and "
+				"0x%p", buffers[0], buffers[1], buffers[2]);
+		}
+	}
+	if (!drm_data->rtn) {
+		/* Map the memory of swap chain buffers: */
+		for (j = 0 ; j < NUM_BUFFERS ; j++) {
+			EMGD_DEBUG("Calling PVRSRVMapDeviceClassMemoryKM(buffers[%d])", j);
+			err = PVRSRVMapDeviceClassMemoryKM(pp_data, dev_mem_context,
+				buffers[j], &buffers_mem_info[j], &buffers_map_info[j]);
+			if (err != PVRSRV_OK) {
+				TEST_ERROR("[EMGD] PVRSRVMapDeviceClassMemoryKM() "
+					"returned %d\n", err);
+				drm_data->rtn = -1;
+			} else if (NULL == buffers_mem_info[j]) {
+				TEST_ERROR("[EMGD] PVRSRVMapDeviceClassMemoryKM() "
+					"returned a NULL pointer for buffer %d's "
+					"PVRSRV_KERNEL_MEM_INFO\n", j);
+				drm_data->rtn = -1;
+			} else {
+				EMGD_DEBUG("  pvLinAddrKM = 0x%p",
+					buffers_mem_info[j]->pvLinAddrKM);
+				EMGD_DEBUG("  sDevVAddr = 0x%lx",
+					buffers_mem_info[j]->sDevVAddr.uiAddr);
+				EMGD_DEBUG("  ui32Flags = 0x%lx",
+					buffers_mem_info[j]->ui32Flags);
+				EMGD_DEBUG("  ui32AllocSize = %lu = 0x%lx",
+					buffers_mem_info[j]->ui32AllocSize,
+					buffers_mem_info[j]->ui32AllocSize);
+				EMGD_DEBUG("  sMemBlk.sDevVirtAddr = %lu = 0x%lx",
+					buffers_mem_info[j]->sMemBlk.sDevVirtAddr.uiAddr,
+					buffers_mem_info[j]->sMemBlk.sDevVirtAddr.uiAddr);
+				EMGD_DEBUG("  sMemBlk.psIntSysPAddr = 0x%p",
+					buffers_mem_info[j]->sMemBlk.psIntSysPAddr);
+				EMGD_DEBUG("  pvSysBackupBuffer = 0x%p",
+					buffers_mem_info[j]->pvSysBackupBuffer);
+				EMGD_DEBUG("  ui32RefCount = %lu",
+					buffers_mem_info[j]->ui32RefCount);
+				EMGD_DEBUG("  bPendingFree = 0x%d",
+					buffers_mem_info[j]->bPendingFree);
+				EMGD_DEBUG("  psKernelSyncInfo = 0x%p",
+					buffers_mem_info[j]->psKernelSyncInfo);
+			}
+		}
+	}
+
+	if (!drm_data->rtn) {
+		/* Draw green in buffer 1 and red in buffer 2: */
+		for (j = 0 ; j < NUM_BUFFERS ; j++) {
+			unsigned long color;
+			unsigned long *fb =
+				(unsigned long *)buffers_mem_info[j]->pvLinAddrKM;
+			unsigned int pixels = buffers_mem_info[j]->ui32AllocSize / 4;
+
+			switch(j) {
+			case 0:
+				color = fb_color;
+				break;
+			case 1:
+				color = bb1_color;
+				break;
+			case 2:
+				color = bb2_color;
+				break;
+			default:
+				color = WHITE;
+				break;
+			}
+
+			EMGD_DEBUG("   Drawing the color 0x%lx to buffer %u", color, j);
+			EMGD_DEBUG("     About to write to addr = 0x%p", fb);
+			EMGD_DEBUG("     About to write %d (0x%x) pixels",
+				pixels, pixels);
+			for (i = 0 ; i < pixels ; i++) {
+#if 0
+				if (0 == (i % 1024)) {
+					printk("row %3d: fb=0x%p\n", (i / 1024), fb);
+				}
+#endif
+				*fb++ = color;
+			}
+		}
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+} /* create_swap_chain() */
+
+
+
+
+/*!
+ * Flips each of the swap chain buffers, pausing a specified amount of time in
+ * between, so that the color can be seen.
+ */
+static void flip_swap_chain_buffers(int which_device, int which_dimension,
+	unsigned long sleep_time)
+{
+	int j;
+	PVRSRV_ERROR err;
+
+	EMGD_TRACE_ENTER;
+
+
+	if (!drm_data->rtn) {
+		/* Display each of the buffers: */
+#ifndef TURN_ON_INTERRUPTS
+		igd_context_t *context = priv->context;
+		igd_display_h primary = priv->primary;
+		int ret;
+		unsigned long status;
+#endif /* TURN_ON_INTERRUPTS */
+		IMG_RECT clip_rect = {0, 0, dimensions[which_dimension].ui32Width,
+			dimensions[which_dimension].ui32Height};
+
+		/* Sleep for half a second, to give a chance to see the original system
+		 * buffer:
+		 */
+		OS_SLEEP(sleep_time);
+
+		/* Show each of the swap-chain buffers twice: */
+		for (j = 1 ; j < (NUM_BUFFERS+2) ; j++) {
+#ifndef TURN_ON_INTERRUPTS
+			int bailout;
+#endif /* TURN_ON_INTERRUPTS */
+			int buf = j % NUM_BUFFERS;
+
+			EMGD_DEBUG("Calling PVRSRVSwapToDCBufferKM(%d)", buf);
+			err = PVRSRVSwapToDCBufferKM(dev_handle[which_device], buffers[buf],
+#ifdef TURN_ON_INTERRUPTS
+				/* Note: it is interesting to test with swap interval values of
+				 * 0, 63, and 130, which cause (respectively) no queueing,
+				 * immediate flipping but queueing to count-down the swap
+				 * interval, and the 3DD not getting some flips from PVR
+				 * services before the swap chain is destoryed:
+				 */
+				1, NULL, 1, &clip_rect);
+#else /* TURN_ON_INTERRUPTS */
+				0, NULL, 1, &clip_rect);
+#endif /* TURN_ON_INTERRUPTS */
+			if (err != PVRSRV_OK) {
+				TEST_ERROR("[EMGD] PVRSRVSwapToDCBufferKM() returned %d\n",err);
+				drm_data->rtn = -1;
+			} else {
+				TEST_ERROR("[EMGD] PVRSRVSwapToDCBufferKM() swapped to "
+					"buffer %d\n", buf);
+			}
+
+#ifndef TURN_ON_INTERRUPTS
+			/* Test that we can query whether the flip occured: */
+			for (bailout = 18 ; bailout > 0 ; bailout--) {
+				ret = context->dispatch.query_event(primary,
+					IGD_EVENT_FLIP_PENDING, &status);
+				if (0 == status) {
+					break;
+				} else {
+					OS_SLEEP(1000);
+				}
+			}
+			if (0 == bailout) {
+				TEST_ERROR("Buffer flip didn't complete after 17msec\n");
+				drm_data->rtn = -1;
+			}
+#endif /* TURN_ON_INTERRUPTS */
+
+			/* Sleep for half a second, to give a chance to verify the flip
+			 * occured:
+			 */
+			OS_SLEEP(sleep_time);
+		}
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+} /* flip_swap_chain_buffers() */
+
+
+
+
+/*!
+ * Unmaps each swap chain buffer, and then destroys the swap chain.
+ */
+static void destroy_swap_chain(void)
+{
+	int j;
+	PVRSRV_ERROR err;
+
+	EMGD_TRACE_ENTER;
+
+
+	for (j = 0 ; j < NUM_BUFFERS ; j++) {
+		if (NULL != buffers_mem_info[j]) {
+			EMGD_DEBUG("Calling PVRSRVUnmapDeviceClassMemoryKM(buffers[%d])", j);
+			err = PVRSRVUnmapDeviceClassMemoryKM(buffers_mem_info[j]);
+			if (err != PVRSRV_OK) {
+				TEST_ERROR("[EMGD] PVRSRVUnmapDeviceClassMemoryKM(%d) "
+					"returned %d\n", j, err);
+				drm_data->rtn = -1;
+			}
+		}
+	}
+	if (NULL != swap_chain) {
+		EMGD_DEBUG("Calling PVRSRVDestroyDCSwapChainKM()");
+		err = PVRSRVDestroyDCSwapChainKM(swap_chain);
+		if (err != PVRSRV_OK) {
+			TEST_ERROR("[EMGD] PVRSRVDestroyDCSwapChainKM() returned %d\n",err);
+			drm_data->rtn = -1;
+		}
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+} /* destroy_swap_chain() */
+
+
+
+
+/*!
+ * Change the mode, via EMGD HAL functions.
+ */
+static void change_mode(struct drm_device *dev, int which_dim)
+{
+	EMGD_TRACE_ENTER;
+
+
+	/**************************************************************************
+	 *
+	 * Do a mode change (with a new background color of white), external to the
+	 * 3DD (which will invalidate the swap chain) and see that the flips are no
+	 * longer visible:
+	 *
+	 **************************************************************************/
+	if ((!drm_data->rtn) && (num_dims != 0)) {
+		igd_context_t *context = priv->context;
+		unsigned long emgd_pf = IGD_PF_ARGB32;
+		igd_display_info_t *mode_list = NULL;
+		igd_display_info_t *mode = NULL;
+		igd_display_info_t *desired_mode = NULL;
+		int mode_flags = IGD_QUERY_LIVE_MODES;
+		unsigned long byte_stride;
+		igd_framebuffer_info_t primary_fb_info;
+		igd_framebuffer_info_t secondary_fb_info;
+		igd_display_h primary;
+		igd_display_h secondary;
+		int err = 0;
+
+		EMGD_DEBUG("Will attempt to do a mode change...");
+		EMGD_DEBUG("  Target width=%lu, height=%lu",
+			dimensions[which_dim].ui32Width,
+			dimensions[which_dim].ui32Height);
+
+		EMGD_DEBUG("  Calling query_mode_list()");
+		err = context->dispatch.query_mode_list(context, priv->dc,
+			&mode_list, mode_flags);
+		if (err) {
+			TEST_ERROR("The query_mode_list() function returned %d.", err);
+			drm_data->rtn = -1;
+		}
+		if (!drm_data->rtn) {
+			EMGD_DEBUG("  Comparing mode list with target width and height");
+			mode = mode_list;
+			while (mode && (mode->width != IGD_TIMING_TABLE_END)) {
+				byte_stride =  IGD_PF_PIXEL_BYTES(emgd_pf, mode->width);
+				EMGD_DEBUG("    Found a mode w/ width=%d, height=%d, refresh=%d;",
+					mode->width, mode->height, mode->refresh);
+				if ((mode->width == dimensions[which_dim].ui32Width) &&
+					(mode->height == dimensions[which_dim].ui32Height)) {
+					EMGD_DEBUG("      This mode is a match!");
+					desired_mode = mode;
+					break;
+				}
+				mode++;
+			}
+			if (NULL == desired_mode) {
+				TEST_ERROR("  No mode matching the desired width (%lu), "
+					"height (%lu) was found.", dimensions[which_dim].ui32Width,
+					dimensions[which_dim].ui32Height);
+				drm_data->rtn = -1;
+			} else {
+				/* Must set this in order to get the timings setup: */
+				desired_mode->flags |= IGD_DISPLAY_ENABLE;
+			}
+		}
+		if (!drm_data->rtn) {
+			/* Make the mode change by calling alter_displays(): */
+			primary_fb_info.width = desired_mode->width;
+			primary_fb_info.height = desired_mode->height;
+			primary_fb_info.pixel_format = emgd_pf;
+			primary_fb_info.flags = 0;
+			primary_fb_info.allocated = 0;
+			memcpy(&secondary_fb_info, &primary_fb_info,
+				sizeof(igd_framebuffer_info_t));
+
+			EMGD_DEBUG("Calling alter_displays()");
+			err = context->dispatch.alter_displays(context,
+				&primary, desired_mode, &primary_fb_info,
+				&secondary, desired_mode, &secondary_fb_info, priv->dc, 0);
+			if (err) {
+				TEST_ERROR("The alter_displays() function returned %d.", err);
+				drm_data->rtn = -1;
+			}
+		}
+		if (!drm_data->rtn) {
+			/* Update the private copy, like emgd_alter_displays() would do: */
+			priv->primary = primary;
+			priv->secondary = secondary;
+			priv->primary_port_number = (priv->dc & 0xf0) >> 4;
+			priv->secondary_port_number = (priv->dc & 0xf00000) >> 20;
+
+			/* Re-initialize the display values: */
+			err = priv->reinit_3dd(dev);
+			if (err != 0) {
+				TEST_ERROR("The reinit_3dd() function returned %d.", err);
+				drm_data->rtn = -1;
+			} else {
+				EMGD_DEBUG("The MODE CHANGE was SUCCESSFUL");
+			}
+		}
+	}
+
+
+
+	EMGD_TRACE_EXIT;
+
+} /* change_mode() */
+
+
+
+
+
+
+
+
+
+/*!
+ * Test a single/clone DC with lots of buffer flipping and mode changes.
+ */
+static void emgd_test_pvrsrv_single_dc(struct drm_device *dev)
+{
+	EMGD_TRACE_ENTER;
+
+
+	/**************************************************************************
+	 *
+	 * Initialize PVR services (including the 3DD):
+	 *
+	 **************************************************************************/
+	init_pvrsrv();
+	if (!drm_data->rtn) {
+		open_device(DEVICE1);
+	}
+
+
+	/**************************************************************************
+	 *
+	 * Map the frame buffer and paint it blue:
+	 *
+	 **************************************************************************/
+	if (!drm_data->rtn) {
+		map_and_paint_fb(DEVICE1, BLUE);
+	}
+
+
+	/**************************************************************************
+	 *
+	 * Create a swap chain, draw red to one back buffer and green to the
+	 * other; and then flip between the frame buffer and the 2 back buffers:
+	 *
+	 **************************************************************************/
+	if (!drm_data->rtn) {
+		create_swap_chain(DEVICE1, 0, BLUE, RED, GREEN);
+	}
+	if (!drm_data->rtn) {
+		flip_swap_chain_buffers(DEVICE1, 0, 500*1000);
+	}
+
+
+	/**************************************************************************
+	 *
+	 * Do a mode change, external to the 3DD (which will invalidate the swap
+	 * chain) and see that the flips are no longer visible:
+	 *
+	 **************************************************************************/
+	if ((!drm_data->rtn) && (num_dims != 0)) {
+		change_mode(dev, 1);
+	}
+	if (!drm_data->rtn) {
+		flip_swap_chain_buffers(DEVICE1, 0, 500*1000);
+	}
+
+
+	/**************************************************************************
+	 *
+	 * Destroy the old swap chain, and create a new one that has the new
+	 * dimensions; then draw cyan to the frame buffer, yellow to one back
+	 * buffer and magenta to the other; and then flip between the frame buffer
+	 * and the 2 back buffers:
+	 *
+	 **************************************************************************/
+	if (!drm_data->rtn) {
+		destroy_swap_chain();
+	}
+	if (!drm_data->rtn) {
+		create_swap_chain(DEVICE1, 1, CYAN, YELLOW, MAGENTA);
+	}
+	if (!drm_data->rtn) {
+		flip_swap_chain_buffers(DEVICE1, 1, 500*1000);
+	}
+
+
+	/**************************************************************************
+	 *
+	 * Destroy the old swap chain, and create a new one that has different
+	 * dimensions (the original dimensions), which will cause the 3DD to do a
+	 * mode change; then draw blue to the frame buffer, red to one back
+	 * buffer and green to the other; and then flip between the frame buffer
+	 * and the 2 back buffers:
+	 *
+	 **************************************************************************/
+	if (!drm_data->rtn) {
+		destroy_swap_chain();
+	}
+	if (!drm_data->rtn) {
+		create_swap_chain(DEVICE1, 0, BLUE, RED, GREEN);
+	}
+	if (!drm_data->rtn) {
+		flip_swap_chain_buffers(DEVICE1, 0, 500*1000);
+	}
+
+
+	/**************************************************************************
+	 *
+	 * Clean up to avoid an Oops and/or memory leak:
+	 *
+	 **************************************************************************/
+	destroy_swap_chain();
+
+	close_device(DEVICE1);
+	deinit_pvrsrv();
+
+
+	EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_single_dc() */
+
+
+
+
+/*!
+ * Test a DIH/extended DC by opening/mapping the first device and drawing blue
+ * on it, and then by creating a swap chain, and flipping between all buffers.
+ */
+static void emgd_test_pvrsrv_dih_open_dev1(struct drm_device *dev)
+{
+	EMGD_TRACE_ENTER;
+
+
+	/**************************************************************************
+	 *
+	 * Initialize PVR services (including the 3DD):
+	 *
+	 **************************************************************************/
+	init_pvrsrv();
+	if (!drm_data->rtn) {
+		open_device(DEVICE1);
+	}
+
+
+	/**************************************************************************
+	 *
+	 * Map the frame buffer and paint it blue:
+	 *
+	 **************************************************************************/
+	if (!drm_data->rtn) {
+		map_and_paint_fb(DEVICE1, BLUE);
+	}
+	OS_SLEEP(3*1000*1000);
+
+
+	/**************************************************************************
+	 *
+	 * Create a swap chain and flip between all buffers:
+	 *
+	 **************************************************************************/
+	if (!drm_data->rtn) {
+		create_swap_chain(DEVICE1, 0, BLUE, RED, GREEN);
+	}
+	if (!drm_data->rtn) {
+		flip_swap_chain_buffers(DEVICE1, 0, 1000*1000);
+	}
+	if (!drm_data->rtn) {
+		destroy_swap_chain();
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_dih_open_dev1() */
+
+
+
+
+/*!
+ * Continue testing a DIH/extended DC by having EMGD do a mode change on the
+ * first device.
+ */
+static void emgd_test_pvrsrv_dih_change1_dev1(struct drm_device *dev)
+{
+	EMGD_TRACE_ENTER;
+
+
+	if ((!drm_data->rtn) && (num_dims != 0)) {
+		change_mode(dev, 1);
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_dih_change1_dev1() */
+
+
+
+
+/*!
+ * Continue testing a DIH/extended DC by having the 3DD (via PVRSRV) do a mode
+ * change, via the creation of a swap chain, on the first device, and then flip
+ * between all buffers.
+ */
+static void emgd_test_pvrsrv_dih_change2_dev1(struct drm_device *dev)
+{
+	EMGD_TRACE_ENTER;
+
+
+	if (!drm_data->rtn) {
+		create_swap_chain(DEVICE1, 0, BLUE, RED, GREEN);
+	}
+	OS_SLEEP(3*1000*1000);
+	if (!drm_data->rtn) {
+		flip_swap_chain_buffers(DEVICE1, 0, 500*1000);
+	}
+	if (!drm_data->rtn) {
+		destroy_swap_chain();
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_dih_change2_dev1() */
+
+
+
+
+/*!
+ * Close the first device and close PVR services to avoid an Oops and/or
+ * memory leak:
+ */
+static void emgd_test_pvrsrv_dih_close_dev1(struct drm_device *dev)
+{
+	EMGD_TRACE_ENTER;
+
+
+	close_device(DEVICE1);
+	deinit_pvrsrv();
+
+
+	EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_dih_close_dev1() */
+
+
+
+
+/*!
+ * Continue testing a DIH/extended DC by opening/mapping the second device and
+ * drawing red on it.
+ */
+static void emgd_test_pvrsrv_dih_open_dev2(struct drm_device *dev)
+{
+	EMGD_TRACE_ENTER;
+
+
+	/**************************************************************************
+	 *
+	 * Initialize PVR services (including the 3DD):
+	 *
+	 **************************************************************************/
+	if (!drm_data->rtn) {
+		init_pvrsrv();
+	}
+	if (!drm_data->rtn) {
+		open_device(DEVICE2);
+	}
+
+
+	/**************************************************************************
+	 *
+	 * Map the frame buffer and paint it cyan:
+	 *
+	 **************************************************************************/
+	if (!drm_data->rtn) {
+		map_and_paint_fb(DEVICE2, CYAN);
+	}
+	OS_SLEEP(3*1000*1000);
+
+
+	/**************************************************************************
+	 *
+	 * Create a swap chain and flip between all buffers:
+	 *
+	 **************************************************************************/
+	if (!drm_data->rtn) {
+		create_swap_chain(DEVICE2, 0, CYAN, YELLOW, MAGENTA);
+	}
+	if (!drm_data->rtn) {
+		flip_swap_chain_buffers(DEVICE2, 0, 1000*1000);
+	}
+	if (!drm_data->rtn) {
+		destroy_swap_chain();
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_dih_open_dev2() */
+
+
+
+
+/*!
+ * Continue testing a DIH/extended DC by having EMGD do a mode change on the
+ * second device.
+ */
+static void emgd_test_pvrsrv_dih_change1_dev2(struct drm_device *dev)
+{
+	EMGD_TRACE_ENTER;
+
+
+	if ((!drm_data->rtn) && (num_dims != 0)) {
+		change_mode(dev, 1);
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_dih_change1_dev2() */
+
+
+
+
+/*!
+ * Continue testing a DIH/extended DC by having the 3DD (via PVRSRV) do a mode
+ * change, via the creation of a swap chain, on the second device, and then flip
+ * between all buffers.
+ */
+static void emgd_test_pvrsrv_dih_change2_dev2(struct drm_device *dev)
+{
+	EMGD_TRACE_ENTER;
+
+
+	if (!drm_data->rtn) {
+		create_swap_chain(DEVICE2, 0, CYAN, YELLOW, MAGENTA);
+	}
+	OS_SLEEP(3*1000*1000);
+	if (!drm_data->rtn) {
+		flip_swap_chain_buffers(DEVICE2, 0, 500*1000);
+	}
+	if (!drm_data->rtn) {
+		destroy_swap_chain();
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_dih_change2_dev2() */
+
+
+
+
+/*!
+ * Close the second device and close PVR services to avoid an Oops and/or
+ * memory leak:
+ */
+static void emgd_test_pvrsrv_dih_close_dev2(struct drm_device *dev)
+{
+	EMGD_TRACE_ENTER;
+
+
+	close_device(DEVICE2);
+	deinit_pvrsrv();
+
+
+	EMGD_TRACE_EXIT;
+
+} /* emgd_test_pvrsrv_dih_close_dev2() */
+
+
+
+
+
+
+
+
+
+
+/*!
+ * IOCTL to allow a ult test ("drmtest_surface.c") to test our 3rd-party
+ * display driver (3DD) without the need for the user-mode IMG service code.
+ */
+int emgd_test_pvrsrv(struct drm_device *dev, void *arg,
+	struct drm_file *file_priv)
+{
+	EMGD_TRACE_ENTER;
+
+
+	drm_data = arg;
+	priv = dev->dev_private;
+	drm_data->rtn = 0;
+
+
+	/**************************************************************************
+	 *
+	 * Depending on the opcode, call the appropriate function that does the
+	 * test:
+	 *
+	 **************************************************************************/
+	switch (drm_data->opcode) {
+	case SINGLE_DC_SWAPING:
+		emgd_test_pvrsrv_single_dc(dev);
+		break;
+	case DIH_DC_DRAW_OPEN_DEV1:
+		emgd_test_pvrsrv_dih_open_dev1(dev);
+		break;
+	case DIH_DC_MODE_CHANGE1_DEV1:
+		emgd_test_pvrsrv_dih_change1_dev1(dev);
+		break;
+	case DIH_DC_MODE_CHANGE2_DEV1:
+		emgd_test_pvrsrv_dih_change2_dev1(dev);
+		break;
+	case DIH_DC_CLOSE_DEV1:
+		emgd_test_pvrsrv_dih_close_dev1(dev);
+		break;
+	case DIH_DC_DRAW_OPEN_DEV2:
+		emgd_test_pvrsrv_dih_open_dev2(dev);
+		break;
+	case DIH_DC_MODE_CHANGE1_DEV2:
+		emgd_test_pvrsrv_dih_change1_dev2(dev);
+		break;
+	case DIH_DC_MODE_CHANGE2_DEV2:
+		emgd_test_pvrsrv_dih_change2_dev2(dev);
+		break;
+	case DIH_DC_CLOSE_DEV2:
+		emgd_test_pvrsrv_dih_close_dev2(dev);
+		break;
+	}
+
+
+	EMGD_DEBUG("drm_data->rtn = %d", drm_data->rtn);
+	EMGD_DEBUG("Returning 0");
+	EMGD_TRACE_EXIT;
+	return 0;
+} /* emgd_test_pvrsrv() */
diff --git a/drivers/gpu/drm/emgd/emgd/drm/image_data.h b/drivers/gpu/drm/emgd/emgd/drm/image_data.h
new file mode 100755
index 0000000..b48fc0c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/image_data.h
@@ -0,0 +1,33 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: bitmap_data.h
+ * $Revision: 1.4 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+#define DECODE_PNG
+static unsigned char image_data[] = {
+};
diff --git a/drivers/gpu/drm/emgd/emgd/drm/splash_screen.c b/drivers/gpu/drm/emgd/emgd/drm/splash_screen.c
new file mode 100755
index 0000000..f429894
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/splash_screen.c
@@ -0,0 +1,2221 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: splash_screen.c
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the Intel Embedded Graphics EFI Driver Splash Screen implementation
+ *  file. This code shows a splash screen with a customizable icon.
+ *-----------------------------------------------------------------------------
+ */
+#define MODULE_NAME hal.oal
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <memory.h>
+#include "sched.h"
+#include "image_data.h"
+#include "splash_screen.h"
+#include "io.h"
+#include "igd_debug.h"
+
+
+/**
+ * Function to display a splash screen to the user. The splash screen must be
+ * accessible to the kernel mode driver as it has to be displayed immediately
+ * after setting the mode (if requested by the user through config options).
+ *
+ * @param ss_data (IN) a non null pointer to splash screen information like
+ * width, height etc.
+ */
+void display_splash_screen(
+	igd_framebuffer_info_t *fb_info,
+	unsigned char *fb,
+	emgd_drm_splash_screen_t *ss_data)
+{
+	if (image_data[0] == 0x89) {
+		display_png_splash_screen(fb_info, fb, ss_data);
+	} else {
+		display_bmp_splash_screen(fb_info, fb, ss_data);
+	}
+}
+
+/*
+ * This is the function to display the bmp splash screen.
+ *
+ * @param ss_data (IN) a non null pointer to splash screen information like
+ * width, height etc.
+ */
+void display_bmp_splash_screen(
+	igd_framebuffer_info_t *fb_info,
+	unsigned char *fb,
+	emgd_drm_splash_screen_t *ss_data)
+{
+	unsigned char *fb_addr, *icon_temp;
+	unsigned long *fb_addr_long, icon_long;
+	unsigned long bitmap_pitch;
+	short x, y;
+	unsigned long init_x_shift, init_y_shift;
+	unsigned long row, col, fb_index;
+	unsigned long bytecount, temp;
+	unsigned long limit_width, limit_height;
+
+	EMGD_TRACE_ENTER;
+
+	x = (short) ss_data->x;
+	y = (short) ss_data->y;
+
+	if(x < 0) {
+		init_x_shift = (fb_info->width + x) * 4;
+		init_y_shift = (fb_info->height + y) * fb_info->screen_pitch;
+	} else {
+		init_x_shift = x * 4;
+		init_y_shift = y * fb_info->screen_pitch;
+	}
+
+	fb_addr = fb + init_y_shift;
+	bytecount = (unsigned long) image_data[1];
+	bitmap_pitch = ss_data->width * bytecount;
+
+	limit_width = ss_data->width;
+	limit_height = ss_data->height;
+
+	if (x+ss_data->width > fb_info->width) {
+		limit_width = fb_info->width - x;
+	}
+	if (y+ss_data->height > fb_info->height) {
+		limit_height = fb_info->height - y;
+	}
+
+	for(row = 0; row < limit_height; row++) {
+		fb_addr_long =
+			(unsigned long *) &fb_addr[fb_info->screen_pitch * row +
+			init_x_shift];
+		/*
+		 * We are adding 3 bytes here, the first byte indicates BMP or PNG,
+		 * the second byte is the bytecount
+		 * and the third byte is the palette count
+		 */
+		icon_temp = &image_data[3 + (row * bitmap_pitch)];
+		fb_index = 0;
+
+		for(col = 0; col < limit_width; col++) {
+
+			icon_long = *((unsigned long *) &icon_temp[col*bytecount]);
+			switch(bytecount) {
+				case 1:
+					/* 8 bit */
+					temp = (icon_long & 0xFF);
+					icon_long = ((temp & 0xE0)<<16) | ((temp & 0x1C)<<11) |
+						((temp & 0x3)<<6);
+					break;
+				case 2:
+					/* 16 bit */
+					temp = (icon_long & 0xFFFF);
+					icon_long = CONV_16_TO_32_BIT(temp);
+					break;
+			}
+			/*
+			 * For 24 bit we don't really have to do anything as it is
+			 * already in RGB 888 format
+			 */
+			fb_addr_long[fb_index++] = icon_long & 0x00FFFFFF;
+		}
+	}
+	EMGD_TRACE_EXIT;
+}
+
+
+/*
+ * This is the function to display the png splash screen.
+ *
+ * @param ss_data (IN) a non null pointer to splash screen information like
+ * width, height etc.
+ */
+void display_png_splash_screen(
+	igd_framebuffer_info_t *fb_info,
+	unsigned char *fb,
+	emgd_drm_splash_screen_t *ss_data)
+{
+	unsigned long image_size;
+	unsigned long i;
+	unsigned long chunk_size;
+	unsigned long chunk_type;
+	unsigned long iter = PNG_HEADER_SIZE;
+	png_header image_header;
+	png_frame *frames = NULL;
+	png_frame *default_image = NULL;
+	unsigned long gama = 0;
+	unsigned long palette_size = 0;
+	unsigned char *input_data = NULL;
+	unsigned long input_iter = 0;
+	unsigned long apng_num_frames = 0;
+	unsigned long apng_num_plays = 0;
+	unsigned long sequence_number = 0;
+	unsigned long cur_seq_num = 0;
+	unsigned long orig_x = 0;
+	unsigned long orig_y = 0;
+	unsigned long apng_file = 0;
+	unsigned long cur_frame = 0;
+	unsigned char trans_p = 0;
+	unsigned long prev_dispose_op = 0;
+	unsigned short delay_num, delay_den;
+
+	EMGD_TRACE_ENTER;
+
+	/*
+	 * Just incase there is no background and we have alpha values, lets
+	 * use the background specified in ss_data.
+	 */
+	image_header.background = 0xFF000000 | ss_data->bg_color;
+	image_header.background_r = (image_header.background >> 16) & 0xFF;
+	image_header.background_g = (image_header.background >> 8) & 0xFF;
+	image_header.background_b = image_header.background & 0xFF;
+
+	image_size = sizeof(image_data)/sizeof(unsigned char);
+	input_data = (unsigned char *)vmalloc(sizeof(image_data));
+	if (!input_data) {
+		EMGD_ERROR("Out of memory");
+		return;
+	}
+	OS_MEMSET(input_data, 0, sizeof(image_data));
+
+	orig_x = (short) ss_data->x;
+	orig_y = (short) ss_data->y;
+
+	/*
+	 * Lets get the information for the first chunk, which should be
+	 * the header chunk: IHDR.
+	 */
+	read_int_from_stream(image_data, &iter, &chunk_size);
+	read_int_from_stream(image_data, &iter, &chunk_type);
+
+	/*
+	 * Initialize image_header
+	 */
+	image_header.width = 0;
+	image_header.height = 0;
+	image_header.bit_depth = 0;
+	image_header.colour_type = 0;
+	image_header.compression_method = 0;
+	image_header.filter_method = 0;
+	image_header.interlace_method = 0;
+	image_header.bpp = 0;
+	image_header.bytes_pp = 0;
+	image_header.bytes_pl = 0;
+
+	/* Loop through the PNG chunks */
+	while (iter <= image_size) {
+		switch (chunk_type) {
+		case CHUNK_IHDR:
+			read_int_from_stream(image_data, &iter, &image_header.width);
+			read_int_from_stream(image_data, &iter, &image_header.height);
+			image_header.bit_depth = (unsigned char)image_data[iter++];
+			image_header.colour_type = (unsigned char)image_data[iter++];
+			image_header.compression_method = (unsigned char)image_data[iter++];
+			image_header.filter_method = (unsigned char)image_data[iter++];
+			image_header.interlace_method = (unsigned char)image_data[iter++];
+			image_header.x_offset = orig_x;
+			image_header.y_offset = orig_y;
+
+			/* store bits per pixel based on PNG spec */
+			switch (image_header.colour_type) {
+			case COLOR_GREY:
+				image_header.bpp = image_header.bit_depth;
+				break;
+			case COLOR_TRUE:
+				image_header.bpp = 3 * image_header.bit_depth;
+				break;
+			case COLOR_INDEXED:
+				image_header.bpp = image_header.bit_depth;
+				break;
+			case COLOR_GREY_ALPHA:
+				image_header.bpp = 2 * image_header.bit_depth;
+				break;
+			case COLOR_TRUE_ALPHA:
+				image_header.bpp = 4 * image_header.bit_depth;
+				break;
+			}
+			/*
+			 * Adding 7 to the bits per pixel before we divide by 8
+			 * gives us the ceiling of bytes per pixel instead of the floor.
+			 */
+			image_header.bytes_pp = (image_header.bpp + 7) / 8;
+			image_header.bytes_pl =
+				((image_header.width * image_header.bpp) + 7) / 8;
+			break;
+
+		case CHUNK_TRNS:
+			image_header.using_transparency = 1;
+			switch (image_header.colour_type) {
+				case COLOR_GREY:
+					read_short_from_stream(image_data, &iter,
+						&image_header.transparency_r);
+					break;
+				case COLOR_TRUE:
+					read_short_from_stream(image_data, &iter,
+						&image_header.transparency_r);
+					read_short_from_stream(image_data, &iter,
+						&image_header.transparency_g);
+					read_short_from_stream(image_data, &iter,
+						&image_header.transparency_b);
+					break;
+				case COLOR_INDEXED:
+					if (image_header.image_palette) {
+						if (chunk_size > palette_size) {
+							EMGD_ERROR("Palette size is smaller than "
+								"transparency values for the palette");
+						}
+						for (i=0; i<chunk_size; i++) {
+							read_char_from_stream(image_data, &iter, &trans_p);
+							image_header.image_palette[i] &= 0xFFFFFF |
+								((trans_p << 28) | (trans_p << 24));
+						}
+					} else {
+						EMGD_ERROR("Palette has not been initialized yet");
+					}
+					break;
+			}
+			break;
+
+		case CHUNK_BKGD:
+			/* Truecolor */
+			if (image_header.colour_type == COLOR_TRUE_ALPHA ||
+				image_header.colour_type == COLOR_TRUE) {
+
+				switch (image_header.bit_depth) {
+				case 16:
+					read_char_from_stream(image_data, &iter,
+						&image_header.background_r);
+					iter++;
+					read_char_from_stream(image_data, &iter,
+						&image_header.background_g);
+					iter++;
+					read_char_from_stream(image_data, &iter,
+						&image_header.background_b);
+					iter++;
+					break;
+				case 8:
+					iter++;
+					read_char_from_stream(image_data, &iter,
+						&image_header.background_r);
+					iter++;
+					read_char_from_stream(image_data, &iter,
+						&image_header.background_g);
+					iter++;
+					read_char_from_stream(image_data, &iter,
+						&image_header.background_b);
+					break;
+				}
+			}
+
+			/* Grayscale */
+			if (image_header.colour_type == COLOR_GREY_ALPHA ||
+				image_header.colour_type == COLOR_GREY) {
+
+				switch (image_header.bit_depth) {
+				case 16:
+					read_char_from_stream(image_data, &iter,
+						&image_header.background_r);
+					iter++;
+					break;
+				case 8:
+					iter++;
+					read_char_from_stream(image_data, &iter,
+						&image_header.background_r);
+					break;
+				case 4:
+					iter++;
+					read_char_from_stream(image_data, &iter,
+						&image_header.background_r);
+					image_header.background_r =
+						((image_header.background_r >> 4) << 4) |
+						(image_header.background_r >> 4);
+					break;
+				case 2:
+					iter++;
+					read_char_from_stream(image_data, &iter,
+						&image_header.background_r);
+					image_header.background_r =
+						((image_header.background_r >> 2) << 6) |
+						((image_header.background_r >> 2) << 4) |
+						((image_header.background_r >> 2) << 2) |
+						(image_header.background_r >> 2);
+					break;
+				case 1:
+					iter++;
+					read_char_from_stream(image_data, &iter,
+						&image_header.background_r);
+					image_header.background_r =
+						(image_header.background_r << 7) |
+						(image_header.background_r << 6) |
+						(image_header.background_r << 5) |
+						(image_header.background_r << 4) |
+						(image_header.background_r << 3) |
+						(image_header.background_r << 2) |
+						(image_header.background_r << 1) |
+						image_header.background_r;
+					break;
+				}
+				image_header.background_g = image_header.background_r;
+				image_header.background_b = image_header.background_r;
+			}
+
+			image_header.background = 0xFF000000 |
+				image_header.background_r<<16 |
+				image_header.background_g<<8 |
+				image_header.background_b;
+			break;
+
+		case CHUNK_GAMA:
+			read_int_from_stream(image_data, &iter, &gama);
+			break;
+
+		case CHUNK_PLTE:
+			palette_size = chunk_size/3;
+			image_header.image_palette =
+				vmalloc(sizeof(unsigned long) * palette_size);
+			if (!image_header.image_palette) {
+				EMGD_ERROR("Out of memory");
+				return;
+			}
+			OS_MEMSET(image_header.image_palette, 0,
+				sizeof(unsigned long) * palette_size);
+
+			for (i=0; i<palette_size; i++) {
+				image_header.image_palette[i] = (
+					0xFF000000 |
+					((unsigned char)image_data[iter] << 16) |
+					((unsigned char)image_data[iter+1] << 8) |
+					(unsigned char)image_data[iter+2]);
+				iter += 3;
+			}
+			break;
+
+		case CHUNK_IDAT:
+			if (!default_image) {
+				default_image = vmalloc(sizeof(png_header));
+				if (!default_image) {
+					EMGD_ERROR("Out of memory");
+					return;
+				}
+				OS_MEMSET(default_image, 0, sizeof(png_header));
+				default_image->width = image_header.width;
+				default_image->height = image_header.height;
+				default_image->x_offset = 0;
+				default_image->y_offset = 0;
+				default_image->bytes_pp = image_header.bytes_pp;
+				default_image->bytes_pl = image_header.bytes_pl;
+				default_image->blend_op = APNG_BLEND_OP_SOURCE;
+				default_image->dispose_op = APNG_DISPOSE_OP_NONE;
+			}
+			for (i=0; i<chunk_size; i++) {
+				input_data[input_iter++] = image_data[iter++];
+			}
+			break;
+
+		case CHUNK_ACTL:
+			apng_file = 1;
+			read_int_from_stream(image_data, &iter, &apng_num_frames);
+			read_int_from_stream(image_data, &iter, &apng_num_plays);
+			frames = vmalloc(apng_num_frames * sizeof(png_frame));
+			if (!frames) {
+				EMGD_ERROR("Out of memory.");
+				return;
+			}
+			OS_MEMSET(frames, 0, apng_num_frames * sizeof(png_frame));
+			break;
+
+		case CHUNK_FCTL:
+			if (cur_seq_num > 0) {
+				decode_png_data(&image_header,input_data,&frames[cur_frame-1]);
+			} else {
+				if (default_image) {
+					decode_png_data(&image_header, input_data, default_image);
+				}
+			}
+
+			/* Should we wipe out the input_data buffer? */
+			input_iter = 0;
+
+			read_int_from_stream(image_data, &iter, &sequence_number);
+			read_int_from_stream(image_data, &iter, &frames[cur_frame].width);
+			read_int_from_stream(image_data, &iter, &frames[cur_frame].height);
+			read_int_from_stream(image_data, &iter, &frames[cur_frame].x_offset);
+			read_int_from_stream(image_data, &iter, &frames[cur_frame].y_offset);
+			read_short_from_stream(image_data, &iter, &delay_num);
+			read_short_from_stream(image_data, &iter, &delay_den);
+			read_char_from_stream(image_data, &iter, &frames[cur_frame].dispose_op);
+			read_char_from_stream(image_data, &iter, &frames[cur_frame].blend_op);
+
+			if (delay_num) {
+				if (!delay_den) {
+					frames[cur_frame].delay = 10000 * (unsigned long)delay_num;
+				} else {
+					frames[cur_frame].delay = (1000000 *
+						(unsigned long)delay_num) / (unsigned long)delay_den;
+				}
+			}
+
+			/*
+			 * Adding 7 to the bits per pixel before we divide by 8
+			 * gives us the ceiling of bytes per pixel instead of the floor.
+			 */
+			frames[cur_frame].bytes_pp = (image_header.bpp + 7) / 8;
+			frames[cur_frame].bytes_pl =
+				((frames[cur_frame].width * image_header.bpp) + 7) / 8;
+
+			cur_frame++;
+
+			if (sequence_number != cur_seq_num++) {
+				EMGD_ERROR("Sequence numbers do not match!");
+				return;
+			}
+			break;
+
+		case CHUNK_FDAT:
+			read_int_from_stream(image_data, &iter, &sequence_number);
+			if (sequence_number != cur_seq_num++) {
+				EMGD_ERROR("Sequence numbers do not match!");
+				return;
+			}
+			for (i=4; i<chunk_size; i++) {
+				input_data[input_iter++] = image_data[iter++];
+			}
+			break;
+
+		case CHUNK_IEND:
+			if (!frames && default_image) {
+				decode_png_data(&image_header, input_data,
+					default_image);
+			} else {
+				decode_png_data(&image_header, input_data,
+					&frames[cur_frame-1]);
+			}
+			break;
+
+		default:
+			iter += chunk_size;
+			break;
+		}
+
+		/*
+		 * Skip over the CRC for now, do we actually want to spend
+		 * time checking this? Per the spec, unless there is an a corrupted
+		 * header, the only possible outcome is a corrupted image.  It's
+		 * either that, or we don't display any image, maybe in this case we
+		 * should display a blue screen. :)
+		 */
+		iter += 4;
+
+		/* Get the next chunk */
+		read_int_from_stream(image_data, &iter, &chunk_size);
+		read_int_from_stream(image_data, &iter, &chunk_type);
+	}
+
+	if (input_data) {
+		vfree(input_data);
+		input_data = NULL;
+	}
+
+	if (apng_file && !apng_num_plays) {
+		apng_num_plays = 20;
+	}
+	if (apng_num_frames > 0) {
+		frames[apng_num_frames-1].dispose_op = APNG_DISPOSE_OP_NONE;
+		if (frames[0].dispose_op == APNG_DISPOSE_OP_PREVIOUS) {
+			frames[0].dispose_op = APNG_DISPOSE_OP_BACKGROUND;
+		}
+	}
+	for (i=0; i<apng_num_plays; i++) {
+		for (cur_frame=0; cur_frame<apng_num_frames; cur_frame++) {
+			if (cur_frame > 0) {
+				prev_dispose_op = frames[cur_frame-1].dispose_op;
+			}
+			display_png_frame(fb_info, fb, image_header, &frames[cur_frame],
+				prev_dispose_op);
+		}
+	}
+	if (!apng_file) {
+		display_png_frame(fb_info, fb, image_header, default_image,
+			APNG_DISPOSE_OP_NONE);
+	}
+
+	for (cur_frame=0; cur_frame<apng_num_frames; cur_frame++) {
+		if (frames[cur_frame].output) {
+			vfree(frames[cur_frame].output);
+			frames[cur_frame].output = NULL;
+		}
+	}
+	if (frames) {
+		vfree(frames);
+		frames = NULL;
+	}
+
+	if (default_image->output) {
+		vfree(default_image->output);
+		default_image->output = NULL;
+	}
+
+	if (default_image) {
+		vfree(default_image);
+		default_image = NULL;
+	}
+
+	EMGD_TRACE_EXIT;
+}
+
+void display_png_frame(
+	igd_framebuffer_info_t *fb_info,
+	unsigned char *fb,
+	png_header image_header,
+	png_frame *frame,
+	unsigned long prev_dispose_op)
+{
+	unsigned char *fb_addr = NULL;
+	unsigned long *fb_addr_long = NULL;
+	unsigned long init_x_shift, init_y_shift, row, col, j;
+	unsigned char image_alpha;
+	unsigned char background_alpha;
+	unsigned long *previous = NULL;
+
+	if (frame->dispose_op == APNG_DISPOSE_OP_PREVIOUS) {
+		previous = vmalloc(frame->width*frame->height*sizeof(unsigned long));
+		if (!previous) {
+			EMGD_ERROR("Out of memory.");
+			return;
+		}
+	}
+
+	/* Lets position our image at the supplied offsets on the screen */
+	/* TODO: Need to account for negative offset */
+	init_x_shift = (image_header.x_offset + frame->x_offset) *
+		sizeof(unsigned long);
+	init_y_shift = (image_header.y_offset + frame->y_offset) *
+		fb_info->screen_pitch;
+	fb_addr = fb + init_y_shift;
+	fb_addr_long = (unsigned long *) &fb_addr[init_x_shift];
+
+	row = 0;
+	j = 0;
+
+	switch (frame->blend_op) {
+
+	/* Blending against our background color */
+	case APNG_BLEND_OP_SOURCE:
+		while (row < frame->height){
+			col = 0;
+			fb_addr_long = (unsigned long *)
+				&fb_addr[fb_info->screen_pitch * row + init_x_shift];
+
+			if (frame->dispose_op == APNG_DISPOSE_OP_PREVIOUS) {
+				/* Save the previous since we need to dispose to it */
+				OS_MEMCPY((void *)&previous[j], (void *)fb_addr_long,
+					frame->width * sizeof(unsigned long));
+			}
+
+			/* Put together the pixel and output to framebuffer */
+			while (col < frame->width) {
+				image_alpha = frame->output[j]>>24;
+				if (image_alpha){
+					if (image_alpha != 0xFF){
+						background_alpha = (0xFF - image_alpha) & 0xFF;
+
+						frame->output[j] = 0xFF000000 |
+							((((((frame->output[j]&0xFF0000)>>16) *
+								image_alpha)/0xFF) +
+							((((image_header.background&0xFF0000)>>16) *
+								background_alpha)/0xFF))<<16) |
+							((((((frame->output[j]&0x00FF00)>>8) *
+								image_alpha)/0xFF) +
+							((((image_header.background&0x00FF00)>>8) *
+								background_alpha)/0xFF))<<8) |
+							((((((frame->output[j]&0x0000FF)) *
+								image_alpha)/0xFF) +
+							((((image_header.background&0x0000FF)) *
+								background_alpha)/0xFF)));
+					}
+				} else {
+					frame->output[j] = image_header.background;
+				}
+				fb_addr_long[col] = frame->output[j];
+				col++;
+				j++;
+			}
+			row++;
+		}
+		break;
+
+	/* Blending against previous frame */
+	case APNG_BLEND_OP_OVER:
+		while (row < frame->height){
+			col = 0;
+			fb_addr_long = (unsigned long *)
+				&fb_addr[fb_info->screen_pitch * row + init_x_shift];
+
+			if (frame->dispose_op == APNG_DISPOSE_OP_PREVIOUS) {
+				/* Save the previous isince we need to dispose to it */
+				OS_MEMCPY((void *)&previous[j], (void *)fb_addr_long,
+						frame->width * sizeof(unsigned long));
+			}
+
+			/* Blend the pixel with existing framebuffer pixel */
+			while (col < frame->width) {
+				image_alpha = frame->output[j]>>24;
+
+				if (image_alpha){
+					if (image_alpha != 0xFF){
+						background_alpha = (0xFF - image_alpha) & 0xFF;
+
+						frame->output[j] = 0xFF000000 |
+							((((((frame->output[j]&0xFF0000)>>16) *
+								image_alpha)/0xFF) +
+							  ((((fb_addr_long[col]&0xFF0000)>>16) *
+								background_alpha)/0xFF))<<16) |
+							((((((frame->output[j]&0x00FF00)>>8) *
+								image_alpha)/0xFF) +
+							  ((((fb_addr_long[col]&0x00FF00)>>8) *
+								background_alpha)/0xFF))<<8) |
+							((((((frame->output[j]&0x0000FF)) *
+								image_alpha)/0xFF) +
+							  ((((fb_addr_long[col]&0x0000FF)) *
+								background_alpha)/0xFF)));
+					}
+					fb_addr_long[col] = frame->output[j];
+				}
+				col++;
+				j++;
+			}
+			row++;
+		}
+		break;
+	}
+
+	if (frame->delay) {
+		OS_SLEEP(frame->delay);
+	}
+
+	fb_addr = fb + init_y_shift;
+	fb_addr_long = (unsigned long *) &fb_addr[init_x_shift];
+	row = 0;
+
+	/* TODO: It would be better to only do this to the portions of the
+	 * frame that will not get overwritten by the next frame.
+	 */
+	switch (frame->dispose_op) {
+	case APNG_DISPOSE_OP_PREVIOUS:
+		j = 0;
+		while (row < frame->height){
+			fb_addr_long = (unsigned long *)
+				&fb_addr[fb_info->screen_pitch * row + init_x_shift];
+
+			OS_MEMCPY((void *)fb_addr_long, (void *)&previous[j],
+				frame->width * sizeof(unsigned long));
+
+			j+= frame->width;
+			row++;
+		}
+		if (previous) {
+			vfree(previous);
+			previous = NULL;
+		}
+		break;
+	case APNG_DISPOSE_OP_BACKGROUND:
+		while (row < frame->height){
+			fb_addr_long = (unsigned long *)
+				&fb_addr[fb_info->screen_pitch * row + init_x_shift];
+
+			OS_MEMSET((void *)fb_addr_long, image_header.background,
+				frame->width * sizeof(unsigned long));
+
+			row++;
+		}
+		break;
+	}
+}
+
+
+void decode_png_data(
+	png_header *image_header,
+	unsigned char *input_data,
+	png_frame *frame)
+{
+	unsigned char *output;
+	unsigned long output_iter = 0;
+
+	unsigned long iter = 0;
+	unsigned char bit_iter = 0;
+	unsigned long row = 0, col = 0;
+	unsigned long end_of_row;
+	unsigned long j,k,l;
+
+	unsigned char zlib_cmf = 0;
+	unsigned char zlib_flg = 0;
+	unsigned char zlib_cm = 0;
+	unsigned char zlib_cinfo = 0;
+	unsigned char zlib_fcheck = 0;
+	unsigned char zlib_fdict = 0;
+	unsigned char zlib_flevel = 0;
+	unsigned long zlib_dictid = 0;
+
+	huffman_node *length_tree = NULL;
+	huffman_node *distance_tree = NULL;
+
+	unsigned char paeth_a, paeth_b, paeth_c;
+	unsigned long paeth_p, paeth_pa, paeth_pb, paeth_pc;
+
+	unsigned long filter_type = 0;
+	unsigned long bfinal = 0;
+	unsigned long btype = 0;
+	unsigned char compr_len = 0;
+	unsigned char compr_nlen = 0;
+	unsigned int small_color;
+
+	/* Allocate space for out output buffer */
+	output = (unsigned char *)vmalloc(
+		frame->height * frame->bytes_pl + frame->height);
+	if (!output) {
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+	OS_MEMSET(output, 0, frame->height * frame->bytes_pl + frame->height);
+
+	frame->size = frame->height * frame->width * sizeof(unsigned long);
+	frame->output = vmalloc(frame->size);
+	if (!frame->output) {
+		frame->size = 0;
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+	OS_MEMSET(frame->output, 0, frame->size);
+
+	/* Data, this needs to be decompressed per zlib spec */
+	if (!zlib_cmf) {
+		zlib_cmf = (unsigned char)input_data[iter++];
+		zlib_flg = (unsigned char)input_data[iter++];
+		zlib_cm = zlib_cmf & 0xF;
+		zlib_cinfo = (zlib_cmf >> 4) & 0xF;
+		zlib_fcheck = zlib_flg & 0x1F;
+		zlib_fdict = (zlib_flg & 0x20) >> 5;
+		zlib_flevel = (zlib_flg >> 6) & 0x3;
+
+		if (zlib_fdict) {
+			read_int_from_stream(input_data, &iter, &zlib_dictid);
+		}
+	}
+
+	/* Here is where we need to process data as a bit stream */
+	bfinal = 0;
+	while (!bfinal) {
+		read_bits_from_stream(input_data, &iter, &bit_iter, 1, &bfinal);
+		read_bits_from_stream(input_data, &iter, &bit_iter, 2, &btype);
+
+		if (btype == 0){
+
+			if (bit_iter) {
+				iter++;
+				bit_iter = 0;
+			}
+
+			/* No Compression */
+			read_char_from_stream(input_data, &iter, &compr_len);
+			read_char_from_stream(input_data, &iter, &compr_nlen);
+
+			for (j = 0;j < compr_len; j++) {
+				read_char_from_stream(input_data, &iter, &output[j]);
+			}
+
+		} else {
+
+			if (btype == 2){
+
+				/* Compressed with dynamnic Huffman codes */
+				build_dynamic_huffman_tree(
+						input_data,
+						&iter,
+						&bit_iter,
+						&length_tree,
+						&distance_tree);
+			} else {
+
+				/* Compressed with static Huffman codes */
+				build_static_huffman_tree(&length_tree,	&distance_tree);
+			}
+
+			/* Decompress huffman code */
+			decompress_huffman(
+					input_data,
+					&iter,
+					&bit_iter,
+					&length_tree,
+					&distance_tree,
+					output,
+					&output_iter);
+
+			free_node(length_tree);
+			free_node(distance_tree);
+		}
+	}
+
+	row = 0;
+	j = 0;
+	l = 0;
+
+	/*
+	 * Process the scanline filtering
+	 * This filtering works by using a difference from a previous pixel
+	 * instead of full pixel data.
+	 */
+	while (row < frame->height){
+		j = row * frame->bytes_pl + row;
+		end_of_row = j + frame->bytes_pl;
+		filter_type = output[j++];
+
+		switch (filter_type) {
+		case 1:
+			/* Filter type of 1 uses the previous pixel */
+			for (k=j+frame->bytes_pp; k<=end_of_row; k++) {
+				output[k] += output[k-frame->bytes_pp];
+			}
+			break;
+		case 2:
+			/* Filter type of 2 uses the previous row's pixel */
+			if (row) {
+				for (k=j; k<=end_of_row; k++) {
+					output[k] += output[k-frame->bytes_pl-1];
+				}
+			}
+			break;
+		case 3:
+			/*
+			 * Filter type of 3 uses the average of the
+			 * previous pixel and the previous row's pixel
+			 */
+			if (row) {
+				for (k=j; k<j+frame->bytes_pp; k++) {
+					output[k] += output[k-frame->bytes_pl-1]/2;
+				}
+				for (k=j+frame->bytes_pp; k<=end_of_row; k++) {
+					output[k] += (output[k-frame->bytes_pp] +
+						output[k-frame->bytes_pl-1])/2;
+				}
+			} else {
+				for (k=j+frame->bytes_pp; k<=end_of_row; k++) {
+					output[k] = output[k] +
+						output[k-frame->bytes_pp]/2;
+				}
+			}
+			break;
+		case 4:
+			/*
+			 * Filter type of 4 uses this algorithm to
+			 * determine if it should use the previous pixel,
+			 * the previous row's pixel, or the pixel immediately
+			 * before the previous row's pixel.
+			 */
+			for (k=j; k<=end_of_row; k++) {
+
+				if (k >= j + frame->bytes_pp) {
+					paeth_a = output[k-frame->bytes_pp];
+				} else {
+					paeth_a = 0;
+				}
+
+				if (row) {
+					paeth_b = output[k-frame->bytes_pl-1];
+				} else {
+					paeth_b = 0;
+				}
+
+				if (row && k >= j + frame->bytes_pp) {
+					paeth_c = output[k-frame->bytes_pp-frame->bytes_pl-1];
+				} else {
+					paeth_c = 0;
+				}
+
+				paeth_p = paeth_a + paeth_b - paeth_c;
+				paeth_pa = abs(paeth_p - paeth_a);
+				paeth_pb = abs(paeth_p - paeth_b);
+				paeth_pc = abs(paeth_p - paeth_c);
+
+				if (paeth_pa <= paeth_pb && paeth_pa <= paeth_pc) {
+					output[k] += paeth_a;
+				} else if (paeth_pb <= paeth_pc) {
+					output[k] += paeth_b;
+				} else {
+					output[k] += paeth_c;
+				}
+			}
+			break;
+		}
+
+		col = 0;
+
+		/* Put together the pixel and output to framebuffer */
+		while (col < frame->width) {
+
+			/* Truecolor with alpha, 16 bits per component */
+			if (image_header->colour_type == COLOR_TRUE_ALPHA &&
+				image_header->bit_depth == 16) {
+
+				frame->output[l] = (output[j+6]<<24 | output[j]<<16 |
+					output[j+2]<<8 | output[j+4]);
+			}
+
+
+			/* Truecolor with alpha, 8 bits per component */
+			if (image_header->colour_type == COLOR_TRUE_ALPHA &&
+				image_header->bit_depth == 8) {
+
+				frame->output[l] = (output[j+3]<<24 | output[j]<<16 |
+					output[j+1]<<8 | output[j+2]);
+			}
+
+			/* Grayscale with alpha, 16 bits per component */
+			if (image_header->colour_type == COLOR_GREY_ALPHA &&
+				image_header->bit_depth == 16) {
+
+				frame->output[l] = (output[j+2]<<24 | output[j]<<16 |
+					output[j]<<8 | output[j]);
+			}
+
+			/* Grayscale with alpha, 8 bits per component */
+			if (image_header->colour_type == COLOR_GREY_ALPHA &&
+				image_header->bit_depth == 8) {
+
+				frame->output[l] = (output[j+1]<<24 | output[j]<<16 |
+					output[j]<<8 | output[j]);
+
+			}
+
+			/* Truecolor, 16 bits per component */
+			if (image_header->colour_type == COLOR_TRUE &&
+				image_header->bit_depth == 16) {
+
+				if (!image_header->using_transparency ||
+					image_header->transparency_r !=
+					(output[j] | output[j+1]) ||
+					image_header->transparency_g !=
+					(output[j+2] | output[j+3]) ||
+					image_header->transparency_b !=
+					(output[j+4] | output[j+5])) {
+
+					frame->output[l] = (0xFF000000 | output[j]<<16 |
+						output[j+2]<<8 | output[j+4]);
+				}
+			}
+
+			/* Truecolor, 8 bits per component */
+			if (image_header->colour_type == COLOR_TRUE &&
+				image_header->bit_depth == 8) {
+
+				if (!image_header->using_transparency ||
+					image_header->transparency_r != output[j] ||
+					image_header->transparency_g != output[j+1] ||
+					image_header->transparency_b != output[j+2]) {
+
+					frame->output[l] = (0xFF000000 | (output[j]<<16) |
+						(output[j+1]<<8) | (output[j+2]));
+				}
+			}
+
+			/* Grayscale, 16 bits per component */
+			if (image_header->colour_type == COLOR_GREY &&
+				image_header->bit_depth == 16) {
+
+				if (!image_header->using_transparency ||
+					image_header->transparency_r !=
+					(output[j] | output[j+1])) {
+
+					frame->output[l] = (0xFF000000 |(output[j]<<16) |
+						(output[j]<<8) | output[j]);
+				}
+			}
+
+			/* Grayscale, 8 bits per component */
+			if (image_header->colour_type == COLOR_GREY &&
+				 image_header->bit_depth == 8) {
+
+				if (!image_header->using_transparency ||
+					image_header->transparency_r != output[j]) {
+					frame->output[l] = (0xFF000000 | (output[j]<<16) |
+						(output[j]<<8) | output[j]);
+				}
+			}
+
+			/* Grayscale, 4 bits per component */
+			if (image_header->colour_type == COLOR_GREY &&
+				image_header->bit_depth == 4) {
+
+				if (!image_header->using_transparency ||
+					image_header->transparency_r != ((output[j] & 0xF0)>>4)) {
+
+					frame->output[l] =
+						CONV_GS_4_TO_32((output[j] & 0xF0)>>4);
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					if (!image_header->using_transparency ||
+						image_header->transparency_r != (output[j] & 0x0F)) {
+
+						frame->output[l] =
+							CONV_GS_4_TO_32(output[j] & 0x0F);
+					}
+				}
+			}
+
+			/* Grayscale, 2 bits per component */
+			if (image_header->colour_type == COLOR_GREY &&
+				image_header->bit_depth == 2) {
+
+				if (!image_header->using_transparency ||
+					image_header->transparency_r != ((output[j] & 0xC0)>>6)) {
+
+					frame->output[l] =
+						CONV_GS_2_TO_32((output[j] & 0xC0) >> 6);
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					if (!image_header->using_transparency ||
+						image_header->transparency_r != ((output[j] & 0x30)>>4)) {
+
+						frame->output[l] =
+							CONV_GS_2_TO_32((output[j] & 0x30) >> 4);
+					}
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					if (!image_header->using_transparency ||
+						image_header->transparency_r != ((output[j] & 0x0C)>>2)) {
+
+						frame->output[l] =
+							CONV_GS_2_TO_32((output[j] & 0x0C) >> 2);
+					}
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					if (!image_header->using_transparency ||
+						image_header->transparency_r != (output[j] & 0x03)) {
+
+						frame->output[l] =
+							CONV_GS_2_TO_32(output[j] & 0x03);
+					}
+				}
+			}
+
+			/* Grayscale, 1 bit per component */
+			if (image_header->colour_type == COLOR_GREY &&
+				image_header->bit_depth == 1) {
+
+				if (!image_header->using_transparency ||
+					image_header->transparency_r != ((output[j] & 0x80)>>7)) {
+
+					frame->output[l] =
+						CONV_GS_1_TO_32((output[j] & 0x80) >> 7);
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					if (!image_header->using_transparency ||
+						image_header->transparency_r != ((output[j] & 0x40)>>6)) {
+
+						frame->output[l] =
+							CONV_GS_1_TO_32((output[j] & 0x40) >> 6);
+					}
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					if (!image_header->using_transparency ||
+						image_header->transparency_r != ((output[j] & 0x20)>>5)) {
+
+						frame->output[l] =
+							CONV_GS_1_TO_32((output[j] & 0x20) >> 5);
+					}
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					if (!image_header->using_transparency ||
+						image_header->transparency_r != ((output[j] & 0x10)>>4)) {
+
+						frame->output[l] =
+							CONV_GS_1_TO_32((output[j] & 0x10) >> 4);
+					}
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					if (!image_header->using_transparency ||
+						image_header->transparency_r != ((output[j] & 0x08)>>3)) {
+
+						frame->output[l] =
+							CONV_GS_1_TO_32((output[j] & 0x08) >> 3);
+					}
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					if (!image_header->using_transparency ||
+						image_header->transparency_r != ((output[j] & 0x04)>>2)) {
+
+						frame->output[l] =
+							CONV_GS_1_TO_32((output[j] & 0x04) >> 2);
+					}
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					if (!image_header->using_transparency ||
+						image_header->transparency_r != ((output[j] & 0x02)>>1)) {
+
+						frame->output[l] =
+							CONV_GS_1_TO_32((output[j] & 0x02) >> 1);
+					}
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					if (!image_header->using_transparency ||
+						image_header->transparency_r != (output[j] & 0x01)) {
+
+						frame->output[l] =
+							CONV_GS_1_TO_32(output[j] & 0x01);
+					}
+				}
+			}
+
+			/* Palette, 8 bit per component */
+			if (image_header->colour_type == COLOR_INDEXED &&
+				image_header->bit_depth == 8) {
+
+				small_color = output[j];
+				frame->output[l] = 0xFF000000 |
+					image_header->image_palette[small_color];
+			}
+
+			/* Palette, 4 bit per component */
+			if (image_header->colour_type == COLOR_INDEXED &&
+				image_header->bit_depth == 4) {
+
+				small_color = (output[j] & 0xF0) >> 4;
+				frame->output[l] = 0xFF000000 |
+					image_header->image_palette[small_color];
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					small_color = output[j] & 0x0F;
+					frame->output[l] = 0xFF000000 |
+						image_header->image_palette[small_color];
+				}
+			}
+
+			/* Palette, 2 bit per component */
+			if (image_header->colour_type == COLOR_INDEXED &&
+				image_header->bit_depth == 2) {
+
+				small_color = (output[j] & 0xC0) >> 6;
+				frame->output[l] = 0xFF000000 |
+					image_header->image_palette[small_color];
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					small_color = output[j] & 0x30 >> 4;
+					frame->output[l] = 0xFF000000 |
+						image_header->image_palette[small_color];
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					small_color = output[j] & 0x0C >> 2;
+					frame->output[l] = 0xFF000000 |
+						image_header->image_palette[small_color];
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					small_color = output[j] & 0x03;
+					frame->output[l] = 0xFF000000 |
+						image_header->image_palette[small_color];
+				}
+			}
+
+			/* Palette, 1 bit per component */
+			if (image_header->colour_type == COLOR_INDEXED &&
+				image_header->bit_depth == 1) {
+
+				small_color = (output[j] & 0x80) >> 7;
+				frame->output[l] = 0xFF000000 |
+					image_header->image_palette[small_color];
+
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					small_color = (output[j] & 0x40) >> 6;
+					frame->output[l] = 0xFF000000 |
+						image_header->image_palette[small_color];
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					small_color = (output[j] & 0x20) >> 5;
+					frame->output[l] = 0xFF000000 |
+						image_header->image_palette[small_color];
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					small_color = (output[j] & 0x10) >> 4;
+					frame->output[l] = 0xFF000000 |
+						image_header->image_palette[small_color];
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					small_color = (output[j] & 0x08) >> 3;
+					frame->output[l] = 0xFF000000 |
+						image_header->image_palette[small_color];
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					small_color = (output[j] & 0x04) >> 2;
+					frame->output[l] = 0xFF000000 |
+						image_header->image_palette[small_color];
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					small_color = (output[j] & 0x02) >> 1;
+					frame->output[l] = 0xFF000000 |
+						image_header->image_palette[small_color];
+				}
+				if (col + 1 < frame->width) {
+					l++;
+					col++;
+					small_color = (output[j] & 0x01);
+					frame->output[l] = 0xFF000000 |
+						image_header->image_palette[small_color];
+				}
+			}
+
+			j += image_header->bytes_pp;
+			l++;
+			col++;
+			if (l > frame->height * frame->width) {
+				EMGD_ERROR("l is larger than frame output size!");
+				return;
+			}
+		}
+		row++;
+	}
+
+	vfree(output);
+}
+
+/*
+ * This is the function to decompress a huffman tree.
+ *
+ * @param stream (IN) This is the input data stream from which we are reading.
+ * @param iter (IN/OUT) This is the input data stream's char iterator
+ * @param bit_iter (IN/OUT) This is the bit iterator for the particular char we
+ *                          are reading.
+ * @param length_tree (IN) This is the huffman code's length tree.
+ * @param distance_tree (IN) This is the huffman code's distance tree.
+ * @param output (IN/OUT) This is an output stream to which we write out the
+ *                        decompressed huffman data.
+ * @param output_iter (IN/OUT) This is the output iterator.
+ */
+void decompress_huffman(
+	unsigned char *stream,
+	unsigned long *iter,
+	unsigned char *bit_iter,
+	huffman_node **length_tree,
+	huffman_node **distance_tree,
+	unsigned char *output,
+	unsigned long *output_iter)
+{
+
+	unsigned long j,k;
+	huffman_node *final_node;
+	unsigned long extra_value = 0;
+	unsigned long length_value = 0;
+	unsigned long distance_value = 0;
+
+	/* Start going along the bitstream and traversing the tree
+	 * until you get to a leaf
+	 */
+	get_huffman_code(stream, iter, bit_iter, length_tree, &final_node);
+
+	while (final_node->value != 256) {
+
+		if (final_node->value < 256){
+			/* literal value */
+			output[*output_iter] = final_node->value;
+			(*output_iter)++;
+		}
+		if (final_node->value > 256){
+			/* We have the initial length value,
+			 * now get the extra length bits, if any
+			 */
+			extra_value = 0;
+			length_value = 0;
+			for (j=0; j<final_node->extra_bits; j++){
+				extra_value = read_bit_from_stream(stream, iter, bit_iter);
+				length_value += extra_value << j;
+			}
+			length_value += final_node->real;
+
+			/* Now its time to get the distance value */
+			get_huffman_code(stream, iter, bit_iter, distance_tree, &final_node);
+
+			/* Get any extra bits for the distance value */
+			extra_value = 0;
+			distance_value = 0;
+			for (j=0; j<final_node->extra_bits; j++){
+				extra_value = read_bit_from_stream(stream, iter, bit_iter);
+				distance_value += extra_value << j;
+			}
+			distance_value += final_node->real;
+
+			/*
+			 * Now we need to use the distance and length values
+			 * to copy previously existing values
+			 */
+			distance_value = (*output_iter) - distance_value;
+			for (k=0; k<length_value; k++){
+				output[*output_iter] = output[distance_value];
+				(*output_iter)++;
+				distance_value++;
+			}
+		}
+
+		/* Get the next code */
+		get_huffman_code(stream, iter, bit_iter, length_tree, &final_node);
+	}
+}
+
+
+/*
+ * This is the function to build a static huffman tree.
+ *
+ * @param length_tree (OUT) This is the huffman code's length tree.
+ * @param distance_tree (OUT) This is the huffman code's distance tree.
+ */
+void build_static_huffman_tree(
+	huffman_node **length_tree,
+	huffman_node **distance_tree) {
+
+	huffman_node *new_node = NULL;
+	huffman_node *cur_node = NULL;
+	unsigned long j,k;
+	unsigned long running_literal_value = 0;
+	unsigned long running_real_value = 0;
+
+	unsigned long ltree_literal_value[10] =
+		{256,265,269,273,277,  0,280,281,285,144};
+	unsigned long ltree_real_value[10] =
+		{  2, 11, 19, 35, 67,  0,115,131,258,144};
+	unsigned long ltree_literal_length[10] =
+		{  9,  4,  4,  4,  3,144,  1,  4,  3,112};
+	unsigned long ltree_code_start[10] =
+		{  0,  9, 13, 17, 21, 48,192,193,197,400};
+	unsigned long ltree_code_length[10] =
+		{  7,  7,  7,  7,  7,  8,  8,  8,  8,  9};
+	unsigned long ltree_extra_bits[10] =
+		{  0,  1,  2,  3,  4,  0,  4,  5,  0,  0};
+
+	unsigned long dtree_literal_value[15] =
+		{0,4,6, 8,10,12, 14, 16, 18,  20,  22,  24,  26,   28,30};
+	unsigned long dtree_real_value[15] =
+		{1,5,9,17,33,65,129,257,513,1025,2049,4097,8193,16385, 0};
+	unsigned long dtree_literal_length[15] =
+		{4,2,2, 2, 2, 2,  2,  2,  2,   2,   2,   2,   2,    2, 2};
+	unsigned long dtree_code_start[15] =
+		{0,4,6, 8,10,12, 14, 16, 18,  20,  22,  24,  26,   28,30};
+	unsigned long dtree_code_length[15] =
+		{5,5,5, 5, 5, 5,  5,  5,  5,   5,   5,   5,   5,    5, 5};
+	unsigned long dtree_extra_bits[15] =
+		{0,1,2, 3, 4, 5,  6,  7,  8,   9,   10,  11, 12,   13, 0};
+
+	/* Build our Huffman length tree using the fixed codes */
+	new_node = (huffman_node *)kzalloc(sizeof(huffman_node), GFP_KERNEL);
+	if (!new_node) {
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+
+	*length_tree = new_node;
+
+	for (k=0; k<10; k++){
+		running_literal_value = ltree_literal_value[k];
+		running_real_value = ltree_real_value[k];
+		for (j=0; j<ltree_literal_length[k]; j++) {
+			new_node = (huffman_node *)kzalloc(sizeof(huffman_node),GFP_KERNEL);
+			if (!new_node) {
+				EMGD_ERROR("Out of memory.");
+				return;
+			}
+
+			new_node->extra_bits = (unsigned char)ltree_extra_bits[k];
+			new_node->value = running_literal_value;
+			new_node->real = running_real_value;
+			cur_node = *length_tree;
+			add_node(&cur_node,
+					new_node,
+					ltree_code_start[k] + j,
+					ltree_code_length[k]);
+			running_literal_value++;
+			if (ltree_extra_bits[k]){
+				running_real_value += (1<<ltree_extra_bits[k]);
+			}else{
+				running_real_value++;
+			}
+		}
+	}
+
+	/* Build our Huffman distance tree using the fixed codes */
+	new_node = (huffman_node *)kzalloc(sizeof(huffman_node), GFP_KERNEL);
+	if (!new_node) {
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+	*distance_tree = new_node;
+
+	for (k=0; k<15; k++){
+		running_literal_value = dtree_literal_value[k];
+		running_real_value = dtree_real_value[k];
+		for (j=0; j<dtree_literal_length[k]; j++) {
+			new_node = (huffman_node *)kzalloc(sizeof(huffman_node),GFP_KERNEL);
+			if (!new_node) {
+				EMGD_ERROR("Out of memory.");
+				return;
+			}
+			new_node->extra_bits = (unsigned char)dtree_extra_bits[k];
+			new_node->value = running_literal_value;
+			new_node->real = running_real_value;
+			cur_node = *distance_tree;
+			add_node(&cur_node,
+				new_node,
+				dtree_code_start[k] + j,
+				dtree_code_length[k]);
+			running_literal_value++;
+			if (dtree_extra_bits[k]){
+				running_real_value += (1<<dtree_extra_bits[k]);
+			}else{
+				running_real_value++;
+			}
+		}
+	}
+}
+
+
+/*
+ * This is the function to build a dynamic huffman tree.
+ *
+ * @param stream (IN) This is the input data stream from which we are reading.
+ * @param iter (IN/OUT) This is the input data stream's char iterator
+ * @param bit_iter (IN/OUT) This is the bit iterator for the particular char we
+ *                          are reading.
+ * @param length_tree (OUT) This is the huffman code's length tree.
+ * @param distance_tree (OUT) This is the huffman code's distance tree.
+ */
+void build_dynamic_huffman_tree(
+	unsigned char *stream,
+	unsigned long *iter,
+	unsigned char *bit_iter,
+	huffman_node **length_tree,
+	huffman_node **distance_tree) {
+
+	unsigned long j,k;
+	unsigned long clc_order[19] =
+	{16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+	unsigned long clc_lengths[19] =
+	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	unsigned long clc_extra_bits[19] =
+	{2,3,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	unsigned long clc_values[19] =
+	{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18};
+	huffman_node *code_length_tree = NULL;
+	unsigned long dynamic_hlit = 0;
+	unsigned long dynamic_hdist = 0;
+	unsigned long dynamic_hclen = 0;
+
+	unsigned long lit_extra_bits_num[LEN_NUM_DISTINCT_EXTRA_BITS] =
+	{265,4,4,4,4,4,1};
+	unsigned long lit_extra_bits[LEN_NUM_DISTINCT_EXTRA_BITS] =
+	{0,1,2,3,4,5,0};
+	unsigned long *dynamic_lit_code = NULL;
+	unsigned long *dynamic_lit_length = NULL;
+	unsigned long *dynamic_lit_extra_bits = NULL;
+	unsigned long *dynamic_lit_values = NULL;
+	unsigned long *dynamic_lit_real_values = NULL;
+
+	unsigned long dist_extra_bits_num[DIST_NUM_DISTINCT_EXTRA_BITS] =
+	{4,2,2,2,2,2,2,2,2,2,2,2,2,2};
+	unsigned long dist_extra_bits[DIST_NUM_DISTINCT_EXTRA_BITS] =
+	{0,1,2,3,4,5,6,7,8,9,10,11,12,13};
+	unsigned long *dynamic_dist_code = NULL;
+	unsigned long *dynamic_dist_length = NULL;
+	unsigned long *dynamic_dist_extra_bits = NULL;
+	unsigned long *dynamic_dist_values = NULL;
+	unsigned long *dynamic_dist_real_values = NULL;
+
+	unsigned long prev_real = 0;
+	unsigned long code_index;
+	huffman_node *new_node = NULL;
+
+	/* Read some initial information about our dynamic huffman tree */
+	read_bits_from_stream(stream, iter, bit_iter, 5, &dynamic_hlit);
+	read_bits_from_stream(stream, iter, bit_iter, 5, &dynamic_hdist);
+	read_bits_from_stream(stream, iter, bit_iter, 4, &dynamic_hclen);
+
+	dynamic_hlit += 257;
+	dynamic_hdist++;
+	dynamic_hclen += 4;
+
+	/* Build our Huffman length tree using the fixed codes */
+	new_node = (huffman_node *)kzalloc(sizeof(huffman_node), GFP_KERNEL);
+	if (!new_node) {
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+	code_length_tree = new_node;
+
+	/* Get the code lengths */
+	for (k=0; k<19 && k<dynamic_hclen; k++){
+		read_bits_from_stream(stream,
+				iter, bit_iter,	3, &clc_lengths[clc_order[k]]);
+	}
+
+	/* build the code_length tree */
+	if (create_tree(CLC_MAX_BITS, CLC_NUM_CODES,
+				&clc_lengths[0],
+				&clc_extra_bits[0],
+				&clc_values[0],
+				&clc_values[0],
+				&code_length_tree) == 1) {
+		EMGD_ERROR("ERROR: create tree failed\n");
+		return;
+	}
+
+	/* Build the literal/length alphabet */
+	dynamic_lit_code = (unsigned long *)vmalloc(
+			sizeof(unsigned long) * LEN_NUM_CODES);
+	if (!dynamic_lit_code) {
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+	OS_MEMSET(dynamic_lit_code, 0, sizeof(unsigned long) * LEN_NUM_CODES);
+
+	dynamic_lit_length = (unsigned long *)vmalloc(
+			sizeof(unsigned long) * LEN_NUM_CODES);
+	if (!dynamic_lit_length) {
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+	OS_MEMSET(dynamic_lit_length, 0, sizeof(unsigned long) * LEN_NUM_CODES);
+
+	dynamic_lit_extra_bits = (unsigned long *)vmalloc(
+			sizeof(unsigned long) * LEN_NUM_CODES);
+	if (!dynamic_lit_extra_bits) {
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+	OS_MEMSET(dynamic_lit_extra_bits, 0, sizeof(unsigned long)*LEN_NUM_CODES);
+
+	dynamic_lit_values = (unsigned long *)vmalloc(
+			sizeof(unsigned long) * LEN_NUM_CODES);
+	if (!dynamic_lit_values) {
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+	OS_MEMSET(dynamic_lit_values, 0, sizeof(unsigned long)*LEN_NUM_CODES);
+
+	dynamic_lit_real_values = (unsigned long *)vmalloc(
+			sizeof(unsigned long) * LEN_NUM_CODES);
+	if (!dynamic_lit_real_values) {
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+	OS_MEMSET(dynamic_lit_real_values, 0, sizeof(unsigned long)*LEN_NUM_CODES);
+
+	/* build extra information, such as extra bits, values and real_values */
+	prev_real = 2;
+	code_index = 0;
+	for (k=0; k<LEN_NUM_DISTINCT_EXTRA_BITS; k++) {
+		for (j=0; j<lit_extra_bits_num[k]; j++) {
+			dynamic_lit_extra_bits[code_index] = lit_extra_bits[k];
+			dynamic_lit_values[code_index] = code_index;
+
+			if (code_index >= LEN_START_REAL_VALUES){
+				dynamic_lit_real_values[code_index] =
+					prev_real += (1<<dynamic_lit_extra_bits[code_index-1]);
+			} else {
+				dynamic_lit_real_values[code_index] = code_index;
+			}
+			code_index++;
+		}
+	}
+
+	/* Doesn't seem to follow the pattern? */
+	dynamic_lit_real_values[285] = 258;
+
+	/* get code lengths for the literal/length alphabet */
+	get_code_lengths(stream, iter, bit_iter, &code_length_tree,
+			dynamic_hlit, dynamic_lit_length);
+
+	/* allocate tree for literal/length codes */
+	new_node = (huffman_node *)kzalloc(sizeof(huffman_node), GFP_KERNEL);
+	if (!new_node) {
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+	*length_tree = new_node;
+
+	/* build the literal/length tree */
+	if (create_tree(LEN_MAX_BITS, LEN_NUM_CODES,
+				dynamic_lit_length,
+				dynamic_lit_extra_bits,
+				dynamic_lit_values,
+				dynamic_lit_real_values,
+				length_tree) == 1) {
+		EMGD_ERROR("ERROR: create tree failed\n");
+		return;
+	}
+
+	/* free all the literal/length data we are no longer using */
+	vfree(dynamic_lit_code);
+	vfree(dynamic_lit_length);
+	vfree(dynamic_lit_extra_bits);
+	vfree(dynamic_lit_values);
+	vfree(dynamic_lit_real_values);
+
+
+	/* Build the distance alphabet */
+	dynamic_dist_code = (unsigned long *)vmalloc(
+		sizeof(unsigned long) * DIST_NUM_CODES);
+	if (!dynamic_dist_code) {
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+	OS_MEMSET(dynamic_dist_code, 0, sizeof(unsigned long) * DIST_NUM_CODES);
+
+	dynamic_dist_length = (unsigned long *)vmalloc(
+		sizeof(unsigned long) * DIST_NUM_CODES);
+	if (!dynamic_dist_length) {
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+	OS_MEMSET(dynamic_dist_length, 0, sizeof(unsigned long) * DIST_NUM_CODES);
+
+	dynamic_dist_extra_bits = (unsigned long *)vmalloc(
+		sizeof(unsigned long) * DIST_NUM_CODES);
+	if (!dynamic_dist_extra_bits) {
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+	OS_MEMSET(dynamic_dist_extra_bits, 0,
+		sizeof(unsigned long) * DIST_NUM_CODES);
+
+	dynamic_dist_values = (unsigned long *)vmalloc(
+		sizeof(unsigned long) * DIST_NUM_CODES);
+	if (!dynamic_dist_values) {
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+	OS_MEMSET(dynamic_dist_values, 0, sizeof(unsigned long) * DIST_NUM_CODES);
+
+	dynamic_dist_real_values = (unsigned long *)vmalloc(
+		sizeof(unsigned long) * DIST_NUM_CODES);
+	if (!dynamic_dist_real_values) {
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+	OS_MEMSET(dynamic_dist_real_values, 0,
+		sizeof(unsigned long) * DIST_NUM_CODES);
+
+	/* build extra information, such as extra bits, values and real_values */
+	prev_real = 1;
+	code_index = 0;
+	for (k=0; k<DIST_NUM_DISTINCT_EXTRA_BITS; k++) {
+		for (j=0; j<dist_extra_bits_num[k]; j++) {
+			dynamic_dist_extra_bits[code_index] = dist_extra_bits[k];
+			dynamic_dist_values[code_index] = code_index;
+
+			if (code_index >= DIST_START_REAL_VALUES){
+				dynamic_dist_real_values[code_index] =
+					prev_real += (1<<dynamic_dist_extra_bits[code_index-1]);
+			} else {
+				dynamic_dist_real_values[code_index] = code_index+1;
+			}
+			code_index++;
+		}
+	}
+
+	/* get code lengths for the distance alphabet */
+	get_code_lengths(stream, iter, bit_iter, &code_length_tree,
+			dynamic_hdist, dynamic_dist_length);
+
+	/* allocate tree for distance codes */
+	new_node = (huffman_node *)kzalloc(sizeof(huffman_node), GFP_KERNEL);
+	if (!new_node) {
+		EMGD_ERROR("Out of memory.");
+		return;
+	}
+	*distance_tree = new_node;
+
+	/* build the distance tree */
+	if (create_tree(DIST_MAX_BITS, DIST_NUM_CODES,
+				&dynamic_dist_length[0],
+				&dynamic_dist_extra_bits[0],
+				&dynamic_dist_values[0],
+				&dynamic_dist_real_values[0],
+				distance_tree) == 1) {
+		EMGD_ERROR("ERROR: create tree failed.\n");
+		return;
+	}
+
+	/* free all the distance data we are no longer using */
+	vfree(dynamic_dist_code);
+	vfree(dynamic_dist_length);
+	vfree(dynamic_dist_extra_bits);
+	vfree(dynamic_dist_values);
+	vfree(dynamic_dist_real_values);
+
+	/* All done with the code length tree, lets free this memory */
+	free_node(code_length_tree);
+}
+
+
+/*
+ * This is the function to get the dynamic code lengths for a specified
+ * number of code lenths. There is some overuse of the word code and code
+ * lengths, but thats sort of the way the PNG spec is.  This is because
+ * we use codes to decode compressed codes.
+ *
+ * @param stream (IN) This is the input data stream from which we are reading.
+ * @param iter (IN/OUT) This is the input data stream's char iterator
+ * @param bit_iter (IN/OUT) This is the bit iterator for the particular char we
+ *                          are reading.
+ * @param code_length_tree (IN) This is the huffman code length tree, which is
+ *                              used to get the code lengths.
+ * @param num_lengths (IN) The number of code lengths.
+ * @param dynamic_lengths (OUT) Gets the dynamic length for the different
+ *                              code lengths
+ */
+void get_code_lengths(
+	unsigned char *stream,
+	unsigned long *iter,
+	unsigned char *bit_iter,
+	huffman_node **code_length_tree,
+	unsigned long num_lengths,
+	unsigned long *dynamic_lengths) {
+
+	unsigned long j,k;
+	huffman_node *final_node;
+	unsigned long dynamic_repeat_length = 0;
+
+	/* get code lengths for the literal/length alphabet */
+	for (k=0; k<num_lengths; k++) {
+		get_huffman_code(stream, iter, bit_iter,
+			code_length_tree, &final_node);
+
+		if (final_node->value < 16){
+			dynamic_lengths[k] = final_node->value;
+		} else {
+			switch (final_node->value) {
+			case 16:
+				/* get repeat length */
+				read_bits_from_stream(stream,
+					iter, bit_iter, 2, &dynamic_repeat_length);
+				dynamic_repeat_length += 3;
+				for (j=0; j<dynamic_repeat_length; j++){
+					dynamic_lengths[k+j] = dynamic_lengths[k-1];
+				}
+				k += j-1;
+				break;
+			case 17:
+				/* get repeat length */
+				read_bits_from_stream(stream,
+					iter, bit_iter, 3, &dynamic_repeat_length);
+				dynamic_repeat_length += 3;
+				for (j=0; j<dynamic_repeat_length; j++){
+					dynamic_lengths[k+j] = 0;
+				}
+				k += j-1;
+				break;
+			case 18:
+				/* get repeat length */
+				read_bits_from_stream(stream,
+					iter, bit_iter, 7, &dynamic_repeat_length);
+				dynamic_repeat_length += 11;
+				for (j=0; j<dynamic_repeat_length; j++){
+					dynamic_lengths[k+j] = 0;
+				}
+				k += j-1;
+				break;
+			}
+		}
+	}
+}
+
+
+/*
+ * This function creates a tree given the necessary tree information.
+ *
+ * @param max_bits (IN) The maximum number of bits for any code
+ * @param num_codes (IN) The number of codes
+ * @param code_lengths (IN) The code lengths
+ * @param extra_bits (IN) The number of extra bits for each huffman code
+ * @param values (IN) The values for the huffman code
+ * @param real_values (IN) The real values for the huffman code
+ * @param tree (OUT) The resulting huffman tree.
+ *
+ * @return 0 on Success
+ * @return >0 on Error
+ */
+int create_tree(
+	unsigned long max_bits,
+	unsigned long num_codes,
+	unsigned long *code_lengths,
+	unsigned long *extra_bits,
+	unsigned long *values,
+	unsigned long *real_values,
+	huffman_node **tree) {
+
+	unsigned long *clc_count;
+	unsigned long *clc_next_code;
+	unsigned long *codes;
+	unsigned long clc_code;
+	unsigned long k;
+	huffman_node *cur_node;
+	huffman_node *new_node;
+
+	if (!tree) {
+		EMGD_ERROR("Bad tree pointer.");
+		return 1;
+	}
+
+	/* Step 1: Count the number of codes for each code length */
+	clc_count = (unsigned long *)vmalloc(
+		sizeof(unsigned long) * (max_bits+1));
+    if (!clc_count) {
+		EMGD_ERROR("Out of memory.");
+		return 1;
+    }
+    OS_MEMSET(clc_count, 0, sizeof(unsigned long) * (max_bits+1));
+
+	for (k=0; k<num_codes; k++){
+		clc_count[code_lengths[k]]++;
+	}
+
+	/* Step 2: Get numerical value of smallest code for each code length */
+	clc_next_code = (unsigned long *)vmalloc(
+		sizeof(unsigned long) * (max_bits+1));
+    if (!clc_next_code) {
+		EMGD_ERROR("Out of memory.");
+		return 1;
+    }
+    OS_MEMSET(clc_next_code, 0, sizeof(unsigned long) * (max_bits+1));
+
+	clc_code = 0;
+	clc_next_code[0] = 2;
+	for (k=1; k<=max_bits; k++){
+	    clc_code = (clc_code + clc_count[k-1]) << 1;
+	    clc_next_code[k] = clc_code;
+	}
+
+	/* Step 3: Assign numerical values to all codes */
+	codes = (unsigned long *)vmalloc(sizeof(unsigned long) * num_codes);
+    if (!codes) {
+		EMGD_ERROR("Out of memory.");
+		return 1;
+    }
+    OS_MEMSET(codes, 0, sizeof(unsigned long) * num_codes);
+
+	for (k=0; k<num_codes; k++){
+	    if (code_lengths[k] > 0){
+			codes[k] = clc_next_code[code_lengths[k]]++;
+
+			/* Add this node to the code length tree */
+			new_node = (huffman_node *)kzalloc(sizeof(huffman_node),GFP_KERNEL);
+			if (!new_node) {
+				EMGD_ERROR("Out of memory.");
+				return 1;
+			}
+
+			new_node->extra_bits = (unsigned char)extra_bits[k];
+			new_node->value = values[k];
+			new_node->real = real_values[k];
+			cur_node = *tree;
+			add_node(&cur_node, new_node, codes[k], code_lengths[k]);
+	    }
+	}
+
+	vfree(clc_count);
+	vfree(clc_next_code);
+	vfree(codes);
+	return 0;
+}
+
+
+/*
+ * This function recursively frees a huffman node and all its sub nodes.
+ * First we free any sub nodes, then we free itself.
+ *
+ * @param node (IN) The huffman node to free.
+ */
+void free_node(huffman_node *node) {
+	if (node->leaf[0]) {
+		free_node((huffman_node *)(node->leaf[0]));
+	}
+	if (node->leaf[1]) {
+		free_node((huffman_node *)(node->leaf[1]));
+	}
+	kfree(node);
+}
+
+
+/*
+ * This function gets a huffman code by traversing through a bit
+ * stream as if those are directions for traversling through
+ * a binary tree.   When we hit a leaf node, we have our value.
+ *
+ * @param stream (IN) This is the input data stream from which we are reading.
+ * @param iter (IN/OUT) This is the input data stream's char iterator
+ * @param bit_iter (IN/OUT) This is the bit iterator for the particular char we
+ *                          are reading.
+ * @param tree (IN) This is the huffman tree.
+ * @param final_node (OUT) The final leaf node we have reached.
+ */
+void get_huffman_code(
+	unsigned char *stream,
+	unsigned long *iter,
+	unsigned char *bit_iter,
+	huffman_node **tree,
+	huffman_node **final_node){
+
+	*final_node = *tree;
+	while ((*final_node)->leaf[0] || (*final_node)->leaf[1]) {
+		(*final_node) = (huffman_node *)(*final_node)->
+			leaf[((stream[*iter] >> *bit_iter) & 1)];
+
+		if (++(*bit_iter) == 8) {
+			(*iter)++;
+			(*bit_iter) = 0;
+		}
+	}
+}
+
+
+/*
+ * This function adds a node into a tree.
+ *
+ * @param tree (IN/OUT) This is the tree's root to which we'll be adding a
+ *                      node.
+ * @param node (IN) This is the node we'll be adding.
+ * @param code (IN) This is the code which will be used as a map to determine
+ *                  where the new node goes on the tree.
+ * @param code_length (IN) This is the code length for the code passed in.
+ *
+ * @return 0 on Success
+ * @return >0 on Error
+ */
+int add_node(
+	huffman_node **tree,
+	huffman_node *node,
+	unsigned long code,
+	unsigned long code_length){
+
+	huffman_node *new_node;
+
+	if (!(*tree)) {
+		EMGD_ERROR("Invalid tree pointer.");
+		return 1;
+	}
+
+	if (code_length > 1){
+
+		/* Build a leaf node if it doesn't exist */
+		if (!(*tree)->leaf[(code >> (code_length-1)) & 1]){
+			new_node = (huffman_node *)kzalloc(sizeof(huffman_node),GFP_KERNEL);
+			if (!new_node) {
+				EMGD_ERROR("Out of memory");
+				return 1;
+			}
+
+			(*tree)->leaf[(code >> (code_length-1)) & 1] =
+				(struct huffman_node *)new_node;
+			(*tree) = new_node;
+		} else {
+			(*tree) =
+				(huffman_node *)(*tree)->leaf[(code >> (code_length-1)) & 1];
+		}
+
+		/* Recursively add the tree node */
+		add_node(&(*tree), node, code, --code_length);
+
+	} else {
+		/* This is where our leaf node belongs */
+		(*tree)->leaf[code & 1] = (struct huffman_node *)node;
+	}
+	return 0;
+}
+
+
+/*
+ * This function reads a 4 byte value from a given stream.
+ * This assumes the passed in stream is byte aligned.
+ *
+ * @param stream (IN) The stream from which we are reading.
+ * @param iter (IN/OUT) The stream iterator.
+ * @param value (OUT) The value read from the stream.
+ *
+ * @return 0 on Success
+ * @return >0 on Error
+ */
+int read_int_from_stream(
+	unsigned char *stream,
+	unsigned long *iter,
+	unsigned long *value){
+
+	*value = stream[*iter] << 24 |
+		stream[(*iter)+1] << 16 |
+		stream[(*iter)+2] << 8 |
+		stream[(*iter)+3];
+	*iter += 4;
+	return 0;
+}
+
+
+/*
+ * This function reads a 2 byte value from a given stream.
+ * This assumes the passed in stream is byte aligned.
+ *
+ * @param stream (IN) The stream from which we are reading.
+ * @param iter (IN/OUT) The stream iterator.
+ * @param value (OUT) The value read from the stream.
+ *
+ * @return 0 on Success
+ * @return >0 on Error
+ */
+int read_short_from_stream(
+	unsigned char *stream,
+	unsigned long *iter,
+	unsigned short *value){
+
+	*value = stream[(*iter)] << 8 |
+		stream[(*iter)+1];
+	*iter += 2;
+	return 0;
+}
+
+
+/*
+ * This function reads a 1 byte value from a given stream.
+ * This assumes the passed in stream is byte aligned.
+ *
+ * @param stream (IN) The stream from which we are reading.
+ * @param iter (IN/OUT) The stream iterator.
+ * @param value (OUT) The value read from the stream.
+ *
+ * @return 0 on Success
+ * @return >0 on Error
+ */
+int read_char_from_stream(
+	unsigned char *stream,
+	unsigned long *iter,
+	unsigned char *value){
+
+	*value = stream[*iter];
+	(*iter)++;
+
+	return 0;
+}
+
+
+/*
+ * This function reads a given number of bits from a given stream.
+ * This does not assume the passed in stream is byte aligned.
+ *
+ * @param stream (IN) The stream from which we are reading.
+ * @param iter (IN/OUT) The stream iterator.
+ * @param bit_iter (IN/OUT) The stream's bit iterator.
+ * @param num_bits (IN) The number of bits to read.
+ * @param value (OUT) The value read from the stream.
+ *
+ * @return 0 on Success
+ * @return >0 on Error
+ */
+int read_bits_from_stream(
+	unsigned char *stream,
+	unsigned long *iter,
+	unsigned char *bit_iter,
+	unsigned long num_bits,
+	unsigned long *value){
+
+	unsigned long i;
+	*value = 0;
+
+	for (i=0; i<num_bits; i++){
+		*value += read_bit_from_stream(stream, iter, bit_iter) << i;
+	}
+
+	return 0;
+}
+
+
+/*
+ * This function reads a single bit from a given stream.
+ * This does not assume the passed in stream is byte aligned.
+ *
+ * @param stream (IN) The stream from which we are reading.
+ * @param iter (IN/OUT) The stream iterator.
+ * @param bit_iter (IN/OUT) The stream's bit iterator.
+ *
+ * @return The bit value read.
+ */
+unsigned int read_bit_from_stream(
+	unsigned char *stream,
+	unsigned long *iter,
+	unsigned char *bit_iter){
+
+	unsigned int result = 0;
+
+	/* get our bit */
+	result = (stream[*iter] >> *bit_iter) & 1;
+
+	/* This is faster than above */
+	if (++(*bit_iter) == 8) {
+		(*iter)++;
+		(*bit_iter) = 0;
+	}
+
+	return result;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/drm/splash_screen.h b/drivers/gpu/drm/emgd/emgd/drm/splash_screen.h
new file mode 100755
index 0000000..5fac725
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/splash_screen.h
@@ -0,0 +1,280 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: splash_screen.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the Intel Embedded Graphics EFI Driver Splash Screen header file.
+ *  This file contains data structures pertinent to showing a splash screen
+ *  with a customizable icon.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _SPLASH_SCREEN_H
+#define _SPLASH_SCREEN_H
+
+#include <user_config.h>
+
+#define CONV_16_TO_32_BIT(a) (0xFF000000 | ((a & 0xF800)<<8) |\
+						((a & 0x7E0)<<5) | (a & 0x1F)<<3)
+#define CONV_GS_4_TO_32(a) (0xFF000000 | ((a)<<20) | ((a)<<16) |\
+						((a)<<12) | ((a)<<8) | ((a)<<4) | ((a)))
+
+#define CONV_GS_2_TO_32(a) (0xFF000000 | ((a)<<22) | ((a)<<20) | ((a)<<18) |\
+						((a)<<16) | ((a)<<14) | ((a)<<12) | ((a)<<10) |\
+						((a)<<8) | ((a)<<6) | ((a)<<4) | ((a)<<2) | ((a)))
+
+#define CONV_GS_1_TO_32(a) (0xFF000000 | ((a)<<23) | ((a)<<22) | ((a)<<21) |\
+						((a)<<20) | ((a)<<19) | ((a)<<18) | ((a)<<17) |\
+						((a)<<16) |	((a)<<15) | ((a)<<14) | ((a)<<13) |\
+						((a)<<12) |	((a)<<11) | ((a)<<10) | ((a)<<9) |\
+						((a)<<8) | ((a)<<7) | ((a)<<6) | ((a)<<5) | ((a)<<4) |\
+						((a)<<3) | ((a)<<2) | ((a)<<1) | ((a)))
+
+/* Colour_type options */
+#define COLOR_GREY       0
+#define COLOR_TRUE       2
+#define COLOR_INDEXED    3
+#define COLOR_GREY_ALPHA 4
+#define COLOR_TRUE_ALPHA 6
+
+#define CONV_GS_4_TO_32(a) (0xFF000000 | ((a)<<20) | ((a)<<16) | ((a)<<12) |\
+						((a)<<8) | ((a)<<4) | ((a)))
+
+#define CONV_GS_2_TO_32(a) (0xFF000000 | ((a)<<22) | ((a)<<20) | ((a)<<18) |\
+						((a)<<16) | ((a)<<14) | ((a)<<12) | ((a)<<10) |\
+						((a)<<8) | ((a)<<6) | ((a)<<4) | ((a)<<2) | ((a)))
+
+#define CONV_GS_1_TO_32(a) (0xFF000000 | ((a)<<23) | ((a)<<22) | ((a)<<21) |\
+						((a)<<20) |	((a)<<19) | ((a)<<18) | ((a)<<17) |\
+						((a)<<16) |	((a)<<15) | ((a)<<14) | ((a)<<13) |\
+						((a)<<12) |	((a)<<11) | ((a)<<10) | ((a)<<9) |\
+						((a)<<8) | ((a)<<7) | ((a)<<6) | ((a)<<5) | ((a)<<4) |\
+						((a)<<3) | ((a)<<2) | ((a)<<1) | ((a)))
+
+#define PNG_HEADER_SIZE                   8
+#define PNG_CRC_SIZE                      4
+#define CLC_MAX_BITS                      7
+#define CLC_NUM_CODES                    19
+#define LEN_MAX_BITS                     15
+#define LEN_NUM_CODES                   288
+#define DIST_MAX_BITS                    15
+#define DIST_NUM_CODES                   32
+#define LEN_NUM_DISTINCT_EXTRA_BITS       7
+#define DIST_NUM_DISTINCT_EXTRA_BITS     14
+#define LEN_START_REAL_VALUES           257
+#define DIST_START_REAL_VALUES            1
+#define DISPLAY_START                  8365
+#define DISPLAY_MAX                    8372
+#define DISPLAY_MAX2                   8372
+
+/* Chunk types */
+#define CHUNK_IHDR 0x49484452
+#define CHUNK_SRGB 0x73524742
+#define CHUNK_PHYS 0x70485973
+#define CHUNK_TIME 0x74494D45
+#define CHUNK_BKGD 0x624B4744
+#define CHUNK_TRNS 0x74524E53
+#define CHUNK_CHRM 0x6348524D
+#define CHUNK_GAMA 0x67414D41
+#define CHUNK_ICCP 0x69434350
+#define CHUNK_SBIT 0x73424954
+#define CHUNK_TEXT 0x74455874
+#define CHUNK_ZTXT 0x7A545874
+#define CHUNK_ITXT 0x69545874
+#define CHUNK_HIST 0x68495354
+#define CHUNK_SPLT 0x73504C54
+#define CHUNK_PLTE 0x504C5445
+#define CHUNK_IDAT 0x49444154
+#define CHUNK_IEND 0x49454E44
+
+/* APNG Chunks */
+#define CHUNK_ACTL 0x6163544C
+#define CHUNK_FCTL 0x6663544C
+#define CHUNK_FDAT 0x66644154
+
+/* Colour_type options */
+#define COLOR_GREY       0
+#define COLOR_TRUE       2
+#define COLOR_INDEXED    3
+#define COLOR_GREY_ALPHA 4
+#define COLOR_TRUE_ALPHA 6
+
+/* APNG dispose_op codes */
+#define APNG_DISPOSE_OP_NONE       0
+#define APNG_DISPOSE_OP_BACKGROUND 1
+#define APNG_DISPOSE_OP_PREVIOUS   2
+
+/* APNG blend_op codes */
+#define APNG_BLEND_OP_SOURCE 0
+#define APNG_BLEND_OP_OVER   1
+
+typedef struct _bitmap_header {
+	/* What is the widht and height of the bitmap */
+	unsigned short width;
+	unsigned short height;
+	/* If Negative, from bottom right, how much to go left by */
+	/* If Positive, from top left, how much to go right by */
+	short x_coord;
+	/* If Negative, from bottom right, how much to go up by */
+	/* If Positive, from top left, how much to go down by */
+	short y_coord;
+} bitmap_header;
+
+typedef struct _png_header {
+	unsigned long width;
+	unsigned long height;
+	unsigned long x_offset;
+	unsigned long y_offset;
+	unsigned char bit_depth;
+	unsigned char colour_type;
+	unsigned char compression_method;
+	unsigned char filter_method;
+	unsigned char interlace_method;
+	unsigned long bpp;
+	unsigned long bytes_pp;
+	unsigned long bytes_pl;
+	unsigned long background;
+	unsigned char background_r;
+	unsigned char background_g;
+	unsigned char background_b;
+	unsigned long *image_palette;
+	unsigned long using_transparency;
+	unsigned short transparency_r;
+	unsigned short transparency_g;
+	unsigned short transparency_b;
+} png_header;
+
+typedef struct _png_frame {
+	unsigned long *output;
+	unsigned long size;
+	unsigned long width;
+	unsigned long height;
+	unsigned long x_offset;
+	unsigned long y_offset;
+	unsigned long bytes_pp;
+	unsigned long bytes_pl;
+	unsigned long delay;
+	unsigned char dispose_op;
+	unsigned char blend_op;
+} png_frame;
+
+typedef struct _huffman_node {
+	unsigned long value;
+	unsigned long real;
+	unsigned char extra_bits;
+	struct huffman_node *leaf[2];
+} huffman_node;
+
+void display_png_frame(
+	igd_framebuffer_info_t *fb_info,
+	unsigned char *fb,
+	png_header image_header,
+	png_frame *frame,
+	unsigned long prev_dispose_op);
+void decode_png_data(
+	png_header *image_header,
+	unsigned char *input_data,
+	png_frame *frame);
+int create_tree(
+    unsigned long max_bits,
+    unsigned long num_codes,
+    unsigned long *code_lengths,
+    unsigned long *extra_bits,
+    unsigned long *values,
+    unsigned long *real_values,
+    huffman_node **tree);
+void free_node(huffman_node *node);
+void display_splash_screen(
+	igd_framebuffer_info_t *fb_info,
+	unsigned char *fb,
+	emgd_drm_splash_screen_t *ss_data);
+void display_bmp_splash_screen(
+	igd_framebuffer_info_t *fb_info,
+	unsigned char *fb,
+	emgd_drm_splash_screen_t *ss_data);
+void display_png_splash_screen(
+	igd_framebuffer_info_t *fb_info,
+	unsigned char *fb,
+	emgd_drm_splash_screen_t *ss_data);
+void decompress_huffman(
+    unsigned char *stream,
+    unsigned long *iter,
+    unsigned char *bit_iter,
+    huffman_node **length_tree,
+    huffman_node **distance_tree,
+	unsigned char *output,
+	unsigned long *output_iter);
+void build_static_huffman_tree(
+    huffman_node **length_tree,
+    huffman_node **distance_tree);
+void build_dynamic_huffman_tree(
+    unsigned char *stream,
+    unsigned long *iter,
+    unsigned char *bit_iter,
+    huffman_node **length_tree,
+    huffman_node **distance_tree);
+void get_code_lengths(
+    unsigned char *stream,
+    unsigned long *iter,
+    unsigned char *bit_iter,
+    huffman_node **code_length_tree,
+    unsigned long num_lengths,
+    unsigned long *dynamic_lengths);
+void get_huffman_code(
+    unsigned char *stream,
+    unsigned long *iter,
+    unsigned char *bit_iter,
+    huffman_node **tree,
+    huffman_node **final_node);
+int add_node(
+    huffman_node **tree,
+    huffman_node *node,
+    unsigned long code,
+    unsigned long code_length);
+int read_int_from_stream(
+	unsigned char *stream,
+	unsigned long *iter,
+	unsigned long *value);
+int read_short_from_stream(
+	unsigned char *stream,
+	unsigned long *iter,
+	unsigned short *value);
+int read_char_from_stream(
+	unsigned char *stream,
+	unsigned long *iter,
+	unsigned char *value);
+int read_bits_from_stream(
+    unsigned char *stream,
+    unsigned long *iter,
+    unsigned char *bit_iter,
+    unsigned long num_bits,
+    unsigned long *value);
+unsigned int read_bit_from_stream(
+    unsigned char *stream,
+    unsigned long *iter,
+    unsigned char *bit_iter);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/drm/user_config.c b/drivers/gpu/drm/emgd/emgd/drm/user_config.c
new file mode 100644
index 0000000..cea78e1
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/user_config.c
@@ -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/drivers/gpu/drm/emgd/emgd/drm/user_config.h b/drivers/gpu/drm/emgd/emgd/drm/user_config.h
new file mode 100644
index 0000000..5aca4d8
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/drm/user_config.h
@@ -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/drivers/gpu/drm/emgd/emgd/gmm/gmm.c b/drivers/gpu/drm/emgd/emgd/gmm/gmm.c
new file mode 100644
index 0000000..cb51f93
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/gmm/gmm.c
@@ -0,0 +1,1382 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: gmm.c
+ * $Revision: 1.52 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF 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;
+
+	/* Allocate a new chunk list element */
+	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;
+	}
+	OS_MEMSET(chunk, 0, sizeof(gmm_chunk_t));
+
+	/* Contiguous memory is needed, so set the type to AGP_PHYS_MEMORY */
+	chunk->size = size;
+	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->used = 1;
+	chunk->ref_cnt = 0;
+	chunk->page_addresses = NULL;
+
+	/* Determine the offset value for this chunk */
+	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;
+
+	/* 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;
+#ifdef GMM_CI_CLEANUP
+ 	gmm_chunk_t *del;
+#endif
+	EMGD_TRACE_ENTER;
+
+	/* Locate the specified chunk and mark it as unused */
+	chunk = gmm_context->head_chunk;
+	while (chunk) {
+		if ((chunk->used == 1) && (chunk->size >= size) &&
+			(chunk->type == AGP_PHYS_MEMORY) &&
+			chunk->offset == offset) {			
+
+			emgd_gtt_remove(gmm_context->context, chunk->gtt_mem, chunk->offset);
+
+			chunk->used =0;	
+#ifdef GMM_CI_CLEANUP			
+			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);
+			}
+
+			/* Free the chunk */
+			del = chunk;
+			chunk = chunk->next;
+			OS_FREE(del);
+#endif				
+			
+			EMGD_DEBUG("EXIT  Returning %d", 0);
+			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/drivers/gpu/drm/emgd/emgd/gmm/gtt.c b/drivers/gpu/drm/emgd/emgd/gmm/gtt.c
new file mode 100644
index 0000000..f530ca6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/gmm/gtt.c
@@ -0,0 +1,436 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: gtt.c
+ * $Revision: 1.17 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Manage the GTT.
+ *-----------------------------------------------------------------------------
+ */
+#include <igd_debug.h>
+#include <drmP.h>
+#include <memlist.h>
+#include <io.h>
+#include <memory.h>
+#include <asm/cacheflush.h>
+#include <linux/version.h>
+
+#define PFX "EMGD: "
+
+#define SCR1	0x71410 /* scratch register set by vbios indicating status*/
+#define SCR2	0x71418 /* scratch register set by vbios indicating amount of stolen memory */
+#define FW_ID	0xE1DF0000 /* firmware identifier */
+#define ST_BIT	0x00000004 /* bit2- stolen memory bit */
+#define PSB_PTE_VALID  0x0001
+
+void emgd_free_pages(gmm_mem_buffer_t *mem);
+
+static DEFINE_MUTEX(client_sem);
+static DEFINE_MUTEX(gtt_sem);
+
+struct client_list_struct {
+	struct list_head list;
+	struct vm_area_struct *vma;
+	pid_t pid;
+};
+
+static LIST_HEAD(client_list);
+
+static void ipi_handler(void *null) {
+	//flush_agp_cache(); /* from agp.h */
+	wbinvd();
+}
+
+static void emgd_cache_flush(void) {
+	if (on_each_cpu(ipi_handler, NULL, 1) != 0)
+		panic(PFX "timed out waiting for the other CPUs!\n");
+}
+
+static void tlb_flush(void) {
+	/* If needed, this would flush the SGX/MSVDX mmu TLB's */
+}
+
+/* FIXME - TURNS OUT THAT THIS FUNCTION IS CURRENTLY A NOOP, BECAUSE
+ * client_list NEVER HAS ANYTHING ADDED TO IT.
+ */
+static void invalidate_vma(unsigned long pg_offset, unsigned long bus_addr) {
+	int zap;
+	struct list_head *tmp;
+	struct client_list_struct *entry;
+	unsigned long addr_start=0;
+	unsigned long addr_end=0;
+	unsigned long addr_offset=0;
+	unsigned long vaddr;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	mutex_lock(&client_sem);
+	list_for_each(tmp, &client_list) {
+		entry = list_entry(tmp, struct client_list_struct, list);
+
+		/*
+		 * We need to handle invalidating VMA's that are only mapping
+		 * a portion of the virtual aperture.  Calculate what if
+		 * any invalidated pages need to be zapped
+		 */
+		addr_start = (entry->vma->vm_pgoff << PAGE_SHIFT)
+			- bus_addr;
+		addr_end = addr_start + (entry->vma->vm_end - entry->vma->vm_start);
+		addr_offset = pg_offset << PAGE_SHIFT;
+
+		vaddr = entry->vma->vm_start + (addr_offset - addr_start);
+
+		zap=0;
+		pgd=NULL;
+		pud=NULL;
+		pmd=NULL;
+		pte=NULL;
+
+		/*
+		 * Look up page table entries for all VMAs that currently
+		 * have the virtual aperture mapped -- to see if the page
+		 * has ever faulted
+		 */
+		pgd = pgd_offset(entry->vma->vm_mm, vaddr);
+		if (!pgd_none(*pgd)) {
+			pud = pud_offset(pgd, vaddr);
+			if (!pud_none(*pud)) {
+				pmd = pmd_offset(pud, vaddr);
+				if (!pmd_none(*pmd)) {
+					pte = pte_offset_map(pmd, vaddr);
+					if (!pte_none(*pte)) {
+						zap=1;
+					}
+				}
+			}
+		}
+		/*
+		 * Only zap a page if it falls within the mapped region
+		 * and it has previously faulted
+		 */
+		if (zap && (addr_offset >= addr_start) &&
+				(addr_offset < addr_end)) {
+
+
+			if (!page_mapcount(pte_page(*pte))) {
+				printk(KERN_ERR "[EMGD] ERROR No mapcount\n");
+				printk(KERN_ALERT "[EMGD] ZR %p %08lX %d %d %p\n",
+						pte_page(*pte),
+						pte_page(*pte)->flags, page_count(pte_page(*pte)),
+						page_mapcount(pte_page(*pte)), pte_page(*pte)->mapping);
+			} else {
+				atomic_add_negative(-1, &pte_page(*pte)->_mapcount);
+				put_page(pte_page(*pte));
+#if  (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
+				dec_mm_counter(entry->vma->vm_mm, file_rss);
+#else
+				dec_mm_counter(entry->vma->vm_mm, MM_FILEPAGES);
+#endif
+			}
+
+			pte_clear(entry->vma->vm_mm, vaddr, pte);
+		}
+
+		if(pte) {
+			pte_unmap(pte);
+		}
+	}
+	mutex_unlock(&client_sem);
+}
+
+
+
+/*
+ * Allocate pages from the kernel and store in a page list.
+ */
+gmm_mem_buffer_t *emgd_alloc_pages(unsigned long num_pages, int type) {
+	gmm_mem_buffer_t *mem;
+	size_t list_size;
+	struct page *page;
+	int i;
+	int order;
+
+	mem = (gmm_mem_buffer_t *)kzalloc(sizeof(gmm_mem_buffer_t), GFP_KERNEL);
+	if (mem == NULL) {
+		return NULL;
+	}
+
+	/* First allocate page array */
+	list_size = num_pages * sizeof(struct page *);
+	mem->vmalloc_flag = false;
+
+	if (list_size <= (2 * PAGE_SIZE)) {
+		mem->pages = kmalloc(list_size, GFP_KERNEL | __GFP_NORETRY);
+	}
+
+	if (mem->pages == NULL) {
+		mem->pages = vmalloc(list_size);
+		mem->vmalloc_flag = true;
+	}
+
+	if (mem->pages == NULL) {
+		printk(KERN_ERR "[EMGD] Failed to allocate memory info struct.\n");
+		kfree(mem);
+		return NULL;
+	}
+
+	/*
+	 * If we need phyical contiguous memory, then do things differently.
+	 *   Call alloc_pages(GFP_KERNEL, pages) to allocate all the pages.
+	 *   The page structure returned is just the first page of the group.
+	 *   ? is it a virtual address ?
+	 *
+	 *   mem->pages[0] = virt_to_phys(page)
+	 *   mem->pages[1] = mem->pages[0] + PAGE_SIZE
+	 */
+
+	if ((type == 1) || (type == 0)) {
+	/* Next allocate the pages */
+		for (i = 0; i < num_pages; i++) {
+			page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);
+			if (page == NULL) {
+				/* Error! */
+				printk(KERN_ERR "[EMGD] Memory allocation failure!\n");
+				if (mem->vmalloc_flag) {
+					vfree(mem->pages);
+				} else {
+					kfree(mem->pages);
+				}
+				kfree(mem);
+				return NULL;
+			}
+
+			/* Make sure this page isn't cached */
+			if (set_memory_uc((unsigned long) page_address(page), 1) < 0) {
+				printk(KERN_ERR "[EMGD] Unable to set page attributes for newly"
+					" allocated graphics memory.\n");
+				/* Rely on the fact that we've kept up the data structures: */
+				emgd_free_pages(mem);
+				/* XXX - THIS IS WHAT SOME OLD IEGD CODE DID--A GOOD IDEA??? */
+				set_memory_wb((unsigned long) page_address(page), 1);
+				__free_page(page);
+				return NULL;
+			}
+
+			get_page(page);
+			mem->pages[i] = page;
+			mem->page_count++;
+		}
+	} else {
+		if (num_pages == 1) {
+			order = 0;
+		} else if (num_pages == 4) {
+			order = 2;
+		} else if (num_pages == 8) {
+			order = 3;
+		} else {
+			printk(KERN_ERR "[EMGD] Page count is not valid for physical "
+				"allocation.\n");
+			if (mem->vmalloc_flag) {
+				vfree(mem->pages);
+			} else {
+				kfree(mem->pages);
+			}
+			kfree(mem);
+			return NULL;
+		}
+
+		page = alloc_pages(GFP_KERNEL, order);
+		if (page == NULL) {
+			/* Error! */
+			printk(KERN_ERR "[EMGD] Memory allocation failure!\n");
+			if (mem->vmalloc_flag) {
+				vfree(mem->pages);
+			} else {
+				kfree(mem->pages);
+			}
+			kfree(mem);
+			return NULL;
+		} else {
+			/* Make sure these pages aren't cached */
+			if (set_memory_uc((unsigned long) page_address(page),
+				num_pages) < 0) {
+				printk(KERN_ERR "[EMGD] Unable to set page attributes for newly"
+					" allocated physical graphics memory.\n");
+				/* XXX - THIS IS WHAT SOME OLD IEGD CODE DID--A GOOD IDEA??? */
+				set_memory_wb((unsigned long) page_address(page), num_pages);
+				__free_pages(page, num_pages);
+				if (mem->vmalloc_flag) {
+					vfree(mem->pages);
+				} else {
+					kfree(mem->pages);
+				}
+				kfree(mem);
+				return NULL;
+			}
+
+			get_page(page);
+			mem->pages[0] = page;
+			if (num_pages > 1) {
+				for (i = 1; i < num_pages; i++) {
+					mem->pages[i] = mem->pages[i-1] + 1;
+				}
+			}
+			mem->physical = page_to_phys(mem->pages[0]);
+			mem->page_count = num_pages;
+		}
+	}
+
+	return mem;
+}
+
+/*
+ * Free memory pages.
+ */
+void emgd_free_pages(gmm_mem_buffer_t *mem) {
+	int i;
+	struct page *page;
+
+	for (i = 0; i < mem->page_count; i++) {
+		page = mem->pages[i];
+		/* XXX - THIS IS WHAT SOME OLD IEGD CODE DID--A GOOD IDEA??? */
+		set_memory_wb((unsigned long) page_address(page), 1);
+		put_page(page);
+		__free_page(page);
+		mem->pages[i] = NULL;
+	}
+
+	if (mem->vmalloc_flag) {
+		vfree(mem->pages);
+	} else {
+		kfree(mem->pages);
+	}
+
+	kfree(mem);
+}
+
+
+/*
+ * Need a function to populate the GTT with the pages.
+ *
+ * The caller provides the offset into the GTT where the memory needs
+ * to go.  This simply needs to allocate the pages and insert them
+ * into the GTT.
+ */
+void emgd_gtt_insert(igd_context_t *context,
+		gmm_mem_buffer_t *mem,
+		unsigned long offset)
+{
+	struct page *page;
+	unsigned long pte;
+	unsigned long pg_off;
+	int i, j;
+
+	pg_off = offset >> PAGE_SHIFT;
+
+	/* Check that the offset is within the gtt's range */
+	if ((pg_off + mem->page_count) > context->device_context.gatt_pages) {
+		printk(KERN_ERR "[EMGD] Attempt to insert a offset beyond of GTT range.\n");
+		return;
+	}
+
+	/* Flush before inserting pages into the GTT */
+	emgd_cache_flush();
+	tlb_flush();
+
+
+	/* Insert the pages into the GTT */
+	mutex_lock(&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/drivers/gpu/drm/emgd/emgd/include/cmd.h b/drivers/gpu/drm/emgd/emgd/include/cmd.h
new file mode 100644
index 0000000..e1787ec
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/cmd.h
@@ -0,0 +1,47 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: cmd.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+#ifndef _CMD_H
+#define _CMD_H
+
+
+typedef struct _cmd_queue cmd_queue_t;
+
+int cmd_init(igd_context_t *context);
+
+
+#define CMD_CONTROL_ON   0x1
+#define CMD_CONTROL_OFF  0x2
+
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/context.h b/drivers/gpu/drm/emgd/emgd/include/context.h
new file mode 100644
index 0000000..9d54e6d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/context.h
@@ -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/drivers/gpu/drm/emgd/emgd/include/debug.h b/drivers/gpu/drm/emgd/emgd/include/debug.h
new file mode 100644
index 0000000..3a12fc1
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/debug.h
@@ -0,0 +1,169 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: debug.h
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Contains debug macros
+ *-----------------------------------------------------------------------------
+ */
+#ifndef __DEBUG_H
+#define __DEBUG_H
+
+
+
+#define IGD_PRINTK_PALETTE(p) \
+{ \
+	EMGD_DEBUG("Palette Struct:"); \
+	EMGD_DEBUG_S("    [%4d].id",    (unsigned int) p->palette_id); \
+	EMGD_DEBUG_S("    [%4d].type",  (unsigned int) p->palette_type); \
+	EMGD_DEBUG_S("    [%4d].size",  (unsigned int) p->size); \
+}
+
+#define IGD_PRINTK_3DSTRETCH(p, s, d, f) \
+{ \
+	EMGD_DEBUG("Ring Buffer Struct:"); \
+	EMGD_DEBUG_S("    Priority = [%8d]",       (unsigned int) p); \
+	EMGD_DEBUG_S("    Flags    = [%08x]",      (unsigned int) f); \
+	EMGD_DEBUG_S("    --------------"); \
+	EMGD_DEBUG_S("    Source surface"); \
+	EMGD_DEBUG_S("    --------------"); \
+	EMGD_DEBUG_S("    [%08x].addr",            (unsigned int) s->addr); \
+	EMGD_DEBUG_S("    [%8d].height",           (unsigned int) s->height); \
+	EMGD_DEBUG_S("    [%8d].width",            (unsigned int) s->width); \
+	EMGD_DEBUG_S("    [%8d].pitch",            (unsigned int) s->pitch); \
+	EMGD_DEBUG_S("    [%08x].pixel_format",    (unsigned int) s->pixel_format); \
+	EMGD_DEBUG_S("    -------------------"); \
+	EMGD_DEBUG_S("    Destination surface"); \
+	EMGD_DEBUG_S("    -------------------"); \
+	EMGD_DEBUG_S("    [%8d].offset",           (unsigned int) d->offset); \
+	EMGD_DEBUG_S("    [%8d].pitch",            (unsigned int) d->pitch); \
+	EMGD_DEBUG_S("    [%8d].x1",               (unsigned int) d->x1); \
+	EMGD_DEBUG_S("    [%8d].y1",               (unsigned int) d->y1); \
+	EMGD_DEBUG_S("    [%8d].x2",               (unsigned int) d->x2); \
+	EMGD_DEBUG_S("    [%8d].y2",               (unsigned int) d->y2); \
+	EMGD_DEBUG_S("    [%08x].pixel_format",    (unsigned int) d->pixel_format); \
+	EMGD_DEBUG_S("    [%08x].byte_mask",       (unsigned int) d->byte_mask); \
+}
+
+#define IGD_PRINT_RB_BUFFER(a) \
+{ \
+	EMGD_DEBUG("Ring Buffer Struct:"); \
+	EMGD_DEBUG_S("    [%08x].id",              (unsigned int) a->id); \
+	EMGD_DEBUG_S("    [%08x].size",            (unsigned int) a->size); \
+	EMGD_DEBUG_S("    [%08x].addr",            (unsigned int) a->addr); \
+	EMGD_DEBUG_S("    [%p].virt",             a->virt); \
+	EMGD_DEBUG_S("    [%p].start  = [%08x]",  a->start, (unsigned int) EMGD_READ32(a->start)); \
+	EMGD_DEBUG_S("    [%p].head   = [%08x]",  a->head,  (0x001ffffc & ((unsigned int) EMGD_READ32(a->head)))); \
+	EMGD_DEBUG_S("    [%p].tail   = [%08x]",  a->tail,  (0x001ffff8 & (unsigned int) EMGD_READ32(a->tail))); \
+	EMGD_DEBUG_S("    [%p].ctrl   = [%08x]",  a->ctrl,  (unsigned int) EMGD_READ32(a->ctrl)); \
+	EMGD_DEBUG_S("    [%08x].res",             (unsigned int) a->reservation); \
+}
+
+#define IGD_PRINTK_DISPLAY(display_context) \
+{ \
+	EMGD_DEBUG("Display Context:"); \
+	EMGD_DEBUG_S("    [%8d].plane",  (int) display_context->plane); \
+	EMGD_DEBUG_S("    [%8d].blend",  (int) display_context->blend_operation); \
+	EMGD_DEBUG_S("    [%8d].pipe",   (int) display_context->pipe); \
+	EMGD_DEBUG_S("    [%8d].port",   (int) display_context->port); \
+	EMGD_DEBUG_S("    [%8d].graph",  (int) display_context->alloc_type); \
+	EMGD_DEBUG_S("    [%8d].mode_n", (int) display_context->mode_number); \
+	EMGD_DEBUG_S("    [%8d].ref",    (int) display_context->refresh); \
+	EMGD_DEBUG_S("    [%8d].enable", (int) display_context->enable); \
+	EMGD_DEBUG_S("    [%8d].ulPipe", (int) display_context->ulPipe); \
+	EMGD_DEBUG_S("    [%8d].ulMode", (int) display_context->ulModeNumber); \
+	EMGD_DEBUG_S("    [%8d].ulRef",  (int) display_context->ulRefresh); \
+}
+
+#define IGD_PRINTK_FBINFO(fb_info) \
+{ \
+	EMGD_DEBUG("FrameBuffer Info:"); \
+	EMGD_DEBUG_S("    [%8d].width",  (int) fb_info->width); \
+	EMGD_DEBUG_S("    [%8d].height",  (int) fb_info->height); \
+	EMGD_DEBUG_S("    [%8d].screen_pitch",  (int) fb_info->screen_pitch); \
+	EMGD_DEBUG_S("    [%8x].fb_base_offset",  (unsigned int) fb_info->fb_base_offset); \
+	EMGD_DEBUG_S("    [%8x].pixel_format",  (unsigned int) fb_info->pixel_format); \
+}
+
+#define IGD_PRINTK_PTINFO(pt_info) \
+{ \
+	EMGD_DEBUG("Port Info:"); \
+	EMGD_DEBUG_S("    [%8d].width",  (int) pt_info->width); \
+	EMGD_DEBUG_S("    [%8d].height",  (int) pt_info->height); \
+	EMGD_DEBUG_S("    [%8d].x_offset",  (int) pt_info->x_offset); \
+	EMGD_DEBUG_S("    [%8d].y_offset",  (int) pt_info->y_offset); \
+	EMGD_DEBUG_S("    [%8d].refresh",  (int) pt_info->refresh); \
+	EMGD_DEBUG_S("    [%8d].hsync_start",  (unsigned int) pt_info->hsync_start); \
+	EMGD_DEBUG_S("    [%8d].hsync_end",  (unsigned int) pt_info->hsync_end); \
+	EMGD_DEBUG_S("    [%8d].hblank_start",  (unsigned int) pt_info->hblank_start); \
+	EMGD_DEBUG_S("    [%8d].hblank_end",  (unsigned int) pt_info->hblank_end); \
+	EMGD_DEBUG_S("    [%8d].vsync_start",  (unsigned int) pt_info->vsync_start); \
+	EMGD_DEBUG_S("    [%8d].vsync_end",  (unsigned int) pt_info->vsync_end); \
+	EMGD_DEBUG_S("    [%8d].vblank_start",  (unsigned int) pt_info->vblank_start); \
+	EMGD_DEBUG_S("    [%8d].vblank_end",  (unsigned int) pt_info->vblank_end); \
+	EMGD_DEBUG_S("    [%8x].flags",  (unsigned int) pt_info->flags); \
+}
+
+#define IGD_PRINTK_FBINFO_2(a,b) \
+{ \
+	EMGD_DEBUG("FrameBuffer Info:"); \
+	EMGD_DEBUG_S("    a=[%8d] b=[%8d].width",  (int) (a)->width, (int) (b)->width); \
+	EMGD_DEBUG_S("    a=[%8d] b=[%8d].height",  (int) (a)->height, (int) (b)->height); \
+	EMGD_DEBUG_S("    a=[%8d] b=[%8d].screen_pitch",  (int) (a)->screen_pitch, (int) (b)->screen_pitch); \
+	EMGD_DEBUG_S("    a=[%8x] b=[%8x].fb_base_offset",  (unsigned int) (a)->fb_base_offset, (unsigned int) (b)->fb_base_offset); \
+	EMGD_DEBUG_S("    a=[%8x] b=[%8x].pixel_format",  (unsigned int) (a)->pixel_format, (unsigned int) (b)->pixel_format); \
+}
+
+#define IGD_PRINTK_PTINFO_2(a,b) \
+{ \
+	EMGD_DEBUG("Port Info:"); \
+	EMGD_DEBUG_S("    a=[%8d] b=[%8d].width",  (int) a->width, (int) b->width); \
+	EMGD_DEBUG_S("    a=[%8d] b=[%8d].height",  (int) a->height, (int) b->height); \
+	EMGD_DEBUG_S("    a=[%8d] b=[%8d].x_offset",  (int) a->x_offset, (int) b->x_offset); \
+	EMGD_DEBUG_S("    a=[%8d] b=[%8d].y_offset",  (int) a->y_offset, (int) b->y_offset); \
+	EMGD_DEBUG_S("    a=[%8d] b=[%8d].refresh",  (int) a->refresh, (int) b->refresh); \
+	EMGD_DEBUG_S("    a=[%8d] b=[%8d].hsync_start",  (unsigned int) a->hsync_start, (unsigned int) b->hsync_start); \
+	EMGD_DEBUG_S("    a=[%8d] b=[%8d].hsync_end",  (unsigned int) a->hsync_end, (unsigned int) b->hsync_end); \
+	EMGD_DEBUG_S("    a=[%8d] b=[%8d].hblank_start",  (unsigned int) a->hblank_start, (unsigned int) b->hblank_start); \
+	EMGD_DEBUG_S("    a=[%8d] b=[%8d].hblank_end",  (unsigned int) a->hblank_end, (unsigned int) b->hblank_end); \
+	EMGD_DEBUG_S("    a=[%8d] b=[%8d].vsync_start",  (unsigned int) a->vsync_start, (unsigned int) b->vsync_start); \
+	EMGD_DEBUG_S("    a=[%8d] b=[%8d].vsync_end",  (unsigned int) a->vsync_end, (unsigned int) b->vsync_end); \
+	EMGD_DEBUG_S("    a=[%8d] b=[%8d].vblank_start",  (unsigned int) a->vblank_start, (unsigned int) b->vblank_start); \
+	EMGD_DEBUG_S("    a=[%8d] b=[%8d].vblank_end",  (unsigned int) a->vblank_end, (unsigned int) b->vblank_end); \
+	EMGD_DEBUG_S("    a=[%8x] b=[%8x].flags",  (unsigned int) a->flags, (unsigned int) b->flags); \
+}
+
+#define IGD_PRINT_ICH_GPIO(ich_gpio_base) \
+{ \
+	EMGD_DEBUG("GPIO_USE_SEL = 0x%lx", EMGD_READ_PORT32(ich_gpio_base + 0x0)); \
+	EMGD_DEBUG("GPIO_IO_SEL = 0x%lx", EMGD_READ_PORT32(ich_gpio_base + 0x4)); \
+	EMGD_DEBUG("GPIO_LVL = 0x%lx", EMGD_READ_PORT32(ich_gpio_base + 0xc)); \
+	EMGD_DEBUG("GPIO_INV = 0x%lx", EMGD_READ_PORT32(ich_gpio_base + 0x2c)); \
+	EMGD_DEBUG("GPIO_USE_SEL2 = 0x%lx", EMGD_READ_PORT32(ich_gpio_base + 0x30));\
+	EMGD_DEBUG("GPIO_IO_SEL2 = 0x%lx", EMGD_READ_PORT32(ich_gpio_base + 0x34)); \
+	EMGD_DEBUG("GPIO_LVL2 = 0x%lx", EMGD_READ_PORT32(ich_gpio_base + 0x38)); \
+}
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/decode.h b/drivers/gpu/drm/emgd/emgd/include/decode.h
new file mode 100644
index 0000000..ac2415a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/decode.h
@@ -0,0 +1,76 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: decode.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the internal header file for the video decode module.
+ *-----------------------------------------------------------------------------
+ */
+
+
+#ifndef _IGD_DECODE_H
+#define _IGD_DECODE_H
+
+#include <igd_render.h>  /* For surface definition */
+
+#define IGD_VD_MAX_SURFACES 2048
+
+#define VID_SURFACE(ctx, id) \
+	(((ctx->context_info.surfmap == NULL) ? &surface_list[id] : &surface_list[ctx->context_info.surfmap->slist_index[id]]))
+
+typedef struct _igd_vd_surfmap_table {
+	int active_entries;
+	int total_surfaces;
+	int *slist_index;
+} igd_vd_surfmap_table_t;
+
+typedef struct _igd_vd_surface_list {
+	int allocated;
+	igd_surface_t *surface;
+	int chroma_offset;
+	int stride_mode;
+    /* Used to store driver private data, e.g. decoder specific intermediate status data
+     * extra_info[0-3]: used for decode
+     * extra_info[4]: surface fourcc
+     * extra_info[5]: surface skippeded or not for encode
+     */
+	int extra_info[6];
+	igd_region_t buf;
+	igd_vd_surfmap_table_t* surfmap;
+} igd_vd_surface_list_t;
+
+struct _igd_video_context {
+	igd_vp_name_t profile;
+	igd_ve_name_t entrypoint;
+	igd_vd_surface_list_t *current_render_target;
+	igd_vd_surfmap_table_t *surfmap;
+
+	/*
+	 * The actual hardware/profile context is much larger. The above
+	 * members are device indpendent.
+	 */
+};
+
+#endif /*_IGD_DECODE_H*/
diff --git a/drivers/gpu/drm/emgd/emgd/include/dispatch.h b/drivers/gpu/drm/emgd/emgd/include/dispatch.h
new file mode 100644
index 0000000..c5a371f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/dispatch.h
@@ -0,0 +1,59 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: dispatch.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains helper functions for creating a dispatch table
+ *  for IGD modules.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _HAL_DISPATCH_H
+#define _HAL_DISPATCH_H
+
+#include <context.h>
+
+typedef struct _dispatch_table {
+	unsigned long did;
+	void *table;
+}dispatch_table_t;
+
+static __inline void *dispatch_acquire(
+	igd_context_t *context,
+	dispatch_table_t *list)
+{
+	dispatch_table_t *curr = list;
+	unsigned long did = context->device_context.did;
+
+	while(curr->did != 0) {
+		if(curr->did == did) {
+			return curr->table;
+		}
+		curr++;
+	}
+	return curr->table;
+}
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/dispatch_utils.h b/drivers/gpu/drm/emgd/emgd/include/dispatch_utils.h
new file mode 100644
index 0000000..b6e4f73
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/dispatch_utils.h
@@ -0,0 +1,78 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: dispatch_utils.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file implements common macros that are used throughout the HAL
+ *  for Device Dependent dispatching. This file is used in both the HAL and
+ *  HAL helper libraries, as such it cannot include any HAL data structures
+ *  that are not available to the helper libraries.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _DISPATCH_UTILS_H_
+#define _DISPATCH_UTILS_H_
+
+#include <config.h>
+#include <intelpci.h>
+
+typedef struct _dispatch_table {
+	unsigned long did;
+	void *table;
+}dispatch_table_t;
+
+static __inline void *dispatch_acquire(
+	unsigned long did,
+	dispatch_table_t *list)
+{
+	dispatch_table_t *curr = list;
+
+	while(curr->did != 0) {
+		if(curr->did == did) {
+			return curr->table;
+		}
+		curr++;
+	}
+	return curr->table;
+}
+
+
+#ifdef CONFIG_PLB
+#define DISPATCH_PLB(p) {PCI_DEVICE_ID_VGA_PLB, p},
+#else
+#define DISPATCH_PLB(p)
+#endif
+#ifdef CONFIG_TNC
+#define DISPATCH_TNC(p) {PCI_DEVICE_ID_VGA_TNC, p},
+#define DISPATCH_TNC_A0(p) {PCI_DEVICE_ID_VGA_TNC_A0, p},
+#define DISPATCH_LNC(p) {PCI_DEVICE_ID_VGA_LNC, p},
+#else
+#define DISPATCH_TNC(p)
+#define DISPATCH_TNC_A0(p)
+#define DISPATCH_LNC(p)
+#endif
+#define DISPATCH_END {0, NULL}
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/displayid.h b/drivers/gpu/drm/emgd/emgd/include/displayid.h
new file mode 100644
index 0000000..82a995f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/displayid.h
@@ -0,0 +1,663 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: displayid.h
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Header file for DisplayID.
+ *  Supported DisplayID versions:
+ *  VESA DisplayID Standard Verion 1 12/13/2007
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _DISPLAYID_H
+#define _DISPLAYID_H
+
+#include <pd.h>
+
+/* Max limits for DisplayID structure members */
+#define DISPLAYID_MAX_RANGES        5
+#define DISPLAYID_MAX_NUM_TIMINGS   5
+/* Possible attributes from DisplayID:
+ *     T1, T2, T3, T4, T5
+ *     dual_channel
+ *     panel_depth
+ *     panel_type */
+#define DISPLAYID_MAX_ATTRS        10
+
+/* DisplayID return values */
+#define DISPLAYID_ERROR_PARSE      1
+#define DISPLAYID_READ_AGAIN       2
+#define DISPLAYID_NOT_SUPPORTED    3
+
+/* Print line macro */
+#define DISPLAYID_PRINT_LINE() \
+	EMGD_DEBUG("----------------------------------------------------------")
+
+/* DisplayID Product Type Identifiers */
+#define PRODUCTID_EXTENSION        0x00
+#define PRODUCTID_TEST             0x01
+#define PRODUCTID_PANEL            0x02
+#define PRODUCTID_STANDALONE       0x03
+#define PRODUCTID_TV_RECEIVER      0x04
+#define PRODUCTID_REPEATER         0x05
+
+/* DisplayID Data Block Tags */
+#define DATABLOCK_PRODUCTID        0x00
+#define DATABLOCK_DISPLAY_PARAMS   0x01
+#define DATABLOCK_COLOR_CHARS      0x02
+#define DATABLOCK_TIMING_1_DETAIL  0x03
+#define DATABLOCK_TIMING_2_DETAIL  0x04
+#define DATABLOCK_TIMING_3_SHORT   0x05
+#define DATABLOCK_TIMING_4_DMTID   0x06
+#define DATABLOCK_VESA_TIMING_STD  0x07
+#define DATABLOCK_CEA_TIMING_STD   0x08
+#define DATABLOCK_VIDEO_RANGE      0x09
+#define DATABLOCK_SERIAL_NUMBER    0x0A
+#define DATABLOCK_ASCII_STRING     0x0B
+#define DATABLOCK_DISPLAY_DEVICE   0x0C
+#define DATABLOCK_LVDS_INTERFACE   0x0D
+#define DATABLOCK_TRANSFER_CHAR    0x0E
+#define DATABLOCK_DISPLAY_INTF     0x0F
+#define DATABLOCK_STEREO_INTF      0x10
+#define DATABLOCK_VENDOR_SPECIFIC  0x7F
+#define DATABLOCK_RESERVED         0x80
+
+/*
+ * typedef struct __attribute__((packed)) {
+ * } foo_t;
+ * This isn't available with Microsoft C compiler
+ * So use pragma to enable bytewise packing and at the end
+ * put it back to default.
+ */
+#pragma pack(1)
+/* General Data Block header - Max 251 bytes */
+typedef struct _datablock {
+	unsigned char  tag;                /* data block type */
+	unsigned char  revision:3;
+	unsigned char  reserved:5;
+	unsigned char  payload;
+	unsigned char  payload_data[248];
+} datablock_t;
+
+/* Video Timing Range Limits Data Block.
+ * Note:
+ *   It is used to convey to a source the supported range of vertical and
+ *   horizontal frequencies along with the maximum supported pixel clock.
+ *   For a continuous frequency device any timing that lies within the
+ *   specified range will ensure a displayable image. The picture may not
+ *   be properly sized or centered, as guaranteed with explicitly reported
+ *   timing, but however the display should synchronize to the timing.
+ */
+
+typedef struct _timing_range {
+	unsigned char  tag;                 /* data block type */
+	unsigned char  revision:3;
+	unsigned char  reserved:5;
+	unsigned char  payload;
+
+	struct {
+		unsigned short lsb_min_dclk;
+		unsigned char  msb_min_dclk;
+	} mindclk;
+	struct {
+		unsigned short lsb_max_dclk;
+		unsigned char  msb_max_dclk;
+	} maxdclk;
+	unsigned char  min_hrate;           /* KHz */
+	unsigned char  max_hrate;           /* KHz */
+	unsigned short min_hblank;          /* Pixels */
+	unsigned char  min_vrate;           /* Hz */
+	unsigned char  max_vrate;           /* Hz */
+	unsigned short min_vblank;          /* Lines */
+
+	/* Timing support flags */
+	unsigned char  reserved1:4;
+	unsigned char  discrete_display:1;
+	unsigned char  vesa_cvt_rb:1;
+	unsigned char  vesa_cvt_std:1;
+	unsigned char  interlaced:1;
+
+	/* Because there is no way to define a 3-byte quantity it is not possible
+	 * to directly read the dclks into member variables automatically.
+	 * Therefore 1st read into above dclk bytes and then copy values into
+	 * below fields at the time of parsing. */
+	/* Below members are outside Data Block definition */
+	unsigned long  min_dclk;            /* KHz */
+	unsigned long  max_dclk;            /* KHz */
+} timing_range_t;
+
+/* Data Block Display params - Video input id */
+#define VIDEO_INPUT_LVDS    0x01
+#define VIDEO_INPUT_TMDS    0x02
+#define VIDEO_INPUT_RSDS    0x03
+#define VIDEO_INPUT_DVID    0x04
+#define VIDEO_INPUT_DVII    0x05
+#define VIDEO_INPUT_VESA_M1 0x06
+#define VIDEO_INPUT_HDMI_A  0x07
+#define VIDEO_INPUT_HDMI_B  0x08
+#define VIDEO_INPUT_MDDI    0x09
+#define VIDEO_INPUT_PORT    0x0A
+#define VIDEO_INPUT_1394    0x0B
+#define VIDEO_INPUT_USB     0x0C
+
+/* Aspect Ratios */
+#define TIMING_AR_1_1       0x0    /* 3-bits */
+#define TIMING_AR_5_4       0x1
+#define TIMING_AR_4_3       0x2
+#define TIMING_AR_15_9      0x3
+#define TIMING_AR_16_9      0x4
+#define TIMING_AR_16_10     0x5
+
+/* Data Block Display params - feature support flags */
+typedef struct _display_params {
+	unsigned char  tag;                /* data block type */
+	unsigned char  revision:3;
+	unsigned char  reserved:5;
+	unsigned char  payload;
+
+	unsigned short horz_image_size;    /* horizontal image size in 0.1 mm */
+	unsigned short vert_image_size;    /* vertical image size in 0.1 mm */
+	unsigned short horz_pixels;        /* horizontal pixels */
+	unsigned short vert_pixels;        /* vertical pixels */
+
+	/* Display feature support flags */
+	unsigned char  deinterlacing:1;    /* de-interlacing capable display */
+	unsigned char  reserved1:1;
+	unsigned char  fixed_res:1;        /* fixed resolution display */
+	unsigned char  fixed_timing:1;     /* fixed timing display */
+	unsigned char  dpm_capable:1;      /* VESA DPM capable display */
+	unsigned char  audio_override:1;   /* override audio on video interface */
+	unsigned char  seperate_audio:1;   /* seperate audio input is available */
+	unsigned char  audio_on_video:1;   /* audio available on video interface */
+
+	unsigned char  transfer_gamma;     /* transfer characteristic gamma */
+	unsigned char  aspect_ratio;       /* aspect ratio */
+	unsigned char  native_color_depth:4; /* color bit depth */
+	unsigned char  overall_color_depth:4;/* color bit depth */
+} display_params_t;
+
+
+/* Product Identification Data Block */
+typedef struct _productid {
+	unsigned char  tag;                /* data block type */
+	unsigned char  revision:3;
+	unsigned char  reserved:5;
+	unsigned char  payload;
+
+	char           vendor[3];          /* vendor name code, no NULL char */
+	unsigned short product_code;       /* product code */
+	unsigned long  serial_number;      /* 32-bit serial number */
+	unsigned char  manf_week;          /* manufactured week number */
+	unsigned char  manf_year;          /* # of years after 2000 */
+	unsigned char  string_size;        /* product id string size */
+	char           string[237];        /* product id string max 236 + NULL */
+} productid_t;
+
+/* Color Characteristices Data Block */
+typedef struct _color_char {
+	unsigned char  tag;                /* data block type */
+	unsigned char  revision:3;
+	unsigned char  reserved:5;
+	unsigned char  payload;
+
+	unsigned char  white_points:4;
+	unsigned char  primaries:3;
+	unsigned char  temporal_color:1;
+
+	unsigned short color_x_value:12;   /* 1.5 bytes */
+	unsigned short color_y_value:12;   /* 1.5 bytes: 0.5 from above */
+} color_char_t;
+
+/* Type 1 - DTD - 20 bytes
+ * Notes:
+ * 1. In a Data Block, maximum of 12DTDs x 20bytes = 240bytes can fit.
+ * 2. As part of parsing, DTD data will be read into type1_dtd_t then
+ *    converted into pd_timing_t for IEGD consumption.
+ * 3. There is no limit on maximum number of type 1 timings.
+ *    They can be present not only in basic section but also in the
+ *    extension section as well.
+ */
+typedef struct _type1_dtd {
+	struct {
+		unsigned short lsb_dclk;
+		unsigned char  msb_dclk;
+	} dclk;                                  /*  02-00 [07:00] */
+
+	/* timing options - 1 byte */
+	unsigned char  aspect_ratio:3;
+	unsigned char  reserved:1;
+	unsigned char  interlaced:1;
+	unsigned char  stereo_3d_support:2;
+	unsigned char  preferred:1;
+
+	unsigned short hactive;
+	unsigned short hblank;
+	unsigned short hsync_offset:15;
+	unsigned short hsync_polarity:1;
+	unsigned short hsync_width;
+	unsigned short vactive;
+	unsigned short vblank;
+	unsigned short vsync_offset:15;
+	unsigned short vsync_polarity:1;
+	unsigned short vsync_width;
+} type1_dtd_t;
+
+/* Type 2 - DTD - 11 bytes
+ * Notes:
+ * 1. In a Data Block, maximum of 22DTDs x 11bytes = 242bytes can fit.
+ * 2. As part of parsing, DTD data will be read into type2_dtd_t then
+ *    converted into pd_timing_t for IEGD consumption.
+ * 3. There is no limit on maximum number of type 2 timings.
+ *    They can be present not only in basic section but also in the
+ *    extension section as well.
+ */
+typedef struct _type2_dtd {                   /* bytes: [bits] */
+	struct {
+		unsigned short lsb_dclk;
+		unsigned char  msb_dclk;
+	} dclk;                                  /*  02-00 [07:00] */
+
+	/* timing options - 1 byte */
+	unsigned char  reserved:4;                /*     03 [03:00] */
+	unsigned char  interlaced:1;              /*     03 [04:04] */
+	unsigned char  stereo_3d_support:2;       /*     03 [06:05] */
+	unsigned char  preferred:1;               /*     03 [07:07] */
+
+	unsigned short hactive:9;                 /*  05-04 [08:00] */
+	unsigned short hblank:7;                  /*  05-04 [15:09] */
+	unsigned char  hsync_width:4;             /*     06 [03:00] */
+	unsigned char  hsync_offset:4;            /*     06 [07:04] */
+	unsigned short vactive:12;                /*  08-07 [11:00] */
+	unsigned short reserved1:4;               /*     08 [15:12] */
+
+	unsigned char  vblank;                    /*     09 [07:00] */
+	unsigned char  vsync_width:4;             /*     10 [03:00] */
+	unsigned char  vsync_offset:4;            /*     10 [07:04] */
+} type2_dtd_t;
+
+
+/* Type 3 - DTD - CVT - 3 bytes
+ * Notes:
+ * 1. In a Data Block, maximum of 82timings x 3bytes = 246bytes can fit.
+ * 2. As part of parsing, data will be read into type3_cvt_t then
+ *    it will be made available for IEGD consumption
+ *    either
+ *         by marking in standard timing table
+ *    or
+ *         creating and inserting in pd_timing_t
+ *    based on CVT formula.
+ * 3. There is no limit on maximum number of type 3 timings.
+ *    They can be present not only in basic section but also in the
+ *    extension section as well.
+ */
+typedef struct _type3_cvt {                   /* bytes: [bits] */
+	/* byte 0 - timing options */
+	unsigned char  aspect_ratio:4;
+	unsigned char  cvt_formula:3;
+	unsigned char  preferred:1;
+
+	/* byte 1 - horizontal active */
+	unsigned char  hactive;
+
+	/* byte 2 - other info */
+	unsigned char  refresh:7;
+	unsigned char  interlaced:1;
+} type3_cvt_t;
+
+/* Structure to emulate bit fields for Type1 Std or Type2 CEA timings */
+typedef struct _type_std {
+	unsigned short width;
+	unsigned short height;
+	unsigned short refresh;
+	unsigned long  flags;         /* currently interlaced, rb, aspect ratio */
+} type_std_t;
+
+/* Display Device Data Block */
+/* Analog interface subtype codes */
+#define ANALOG_15HD_VGA     0x0
+#define ANALOG_VESA_NAVI_V  0x1
+#define ANALOG_VESA_NAVI_D  0x2
+
+/* Device technology types */
+#define TECH_CRT            0x0
+#define TECH_LVDS           0x1
+#define TECH_PLASMA         0x2
+#define TECH_EL             0x3   /* Electroluminescent */
+#define TECH_INORG          0x4
+#define TECH_ORG            0x5
+#define TECH_FED            0x6   /* FED or sim. "cold cathode" */
+#define TECH_EP             0x7   /* Electrophoretic */
+#define TECH_EC             0x8   /* Electrochromic */
+#define TECH_EM             0x9   /* Electromechanical */
+#define TECH_EW             0xA   /* Electrowetting */
+#define TECH_OTHER          0xF   /* Othertype not defined here */
+
+/* Device technoloty sub-types */
+#define TECH_CRT_MONO       0x0   /* Mono chrome CRT */
+#define TECH_CRT_STD        0x1   /* Standard tricolor CRT */
+#define TECH_CRT_OTHER      0x2   /* other or undefined */
+
+#define TECH_LVDS_PASSIVE_TN 0x0  /* Passive matrix TN */
+#define TECH_LVDS_PASSIVE_CL 0x1  /* Passive matrix cholesteric LC */
+#define TECH_LVDS_PASSIVE_FE 0x2  /* Passive matrix ferroelectric LC */
+#define TECH_LVDS_PASSIVE_OT 0x3  /* Passive matrix other LC */
+#define TECH_LVDS_ACTIVE_TN  0x4  /* Active matrix TN */
+#define TECH_LVDS_ACTIVE_IPS 0x5  /* Active matrix IPS */
+#define TECH_LVDS_ACTIVE_VA  0x6  /* Active matrix VA */
+#define TECH_LVDS_ACTIVE_OCB 0x7  /* Active matrix OCB */
+#define TECH_LVDS_ACTIVE_FL  0x8  /* Active matrix ferroelectric */
+#define TECH_LVDS_OTHER      0xF  /* Other LVDS technology not defined above */
+
+#define TECH_PLASMA_DC       0x0  /* DC plasma */
+#define TECH_PLASMA_AC       0x1  /* AC plasma */
+
+/* Content protection support */
+#define CP_NOCP              0x0
+#define CP_DTCP              0x2
+#define CP_DPCP              0x3  /* Display port content protection */
+
+/* Display physical orientation information */
+#define DEFAULT_ORIENTATION(a) 		((a & 0xC0) >> 6)
+#define ZERO_PIXEL(a) 				((a & 0x0C) >> 2)
+#define SCAN_DIRECTION(a) 			(a & 0x03)
+
+#define SCAN_DIRECTION_LONG 		0x1 /* Display scan direction (2 bits) */
+#define SCAN_DIRECTION_SHORT 		0x2
+
+#define ZP_UPPER_LEFT 				0x0 /* Zero pixel position (2 bits) */
+#define ZP_UPPER_RIGHT 				0x1
+#define ZP_LOWER_LEFT 				0x2
+#define ZP_LOWER_RIGHT 				0x3
+
+#define DEF_ORIENTATION_LANDSCAPE 	0x0 /* Default orientation (2 bits) */
+#define DEF_ORIENTATION_PORTRAIT 	0x1
+#define DEF_ORIENTATION_UNKNOWN 	0x2
+
+
+typedef struct _display_device {
+	unsigned char  tag;                /* data block type */
+	unsigned char  revision:3;
+	unsigned char  reserved:5;
+	unsigned char  payload;
+
+	unsigned char  tech_subtype:4;
+	unsigned char  tech_type:4;
+	unsigned char  reserved1:2;
+	unsigned char  can_on_off_bklt:1;  /* This bit tells backlight can be
+										* switched on or off using the control
+										* method defined */
+	unsigned char  can_change_bklt:1;  /* This bit tells backlight intensity
+										* can be changed using the control
+										* method defined */
+	unsigned char  op_mode:4;
+
+	unsigned short horz_pixel_count;
+	unsigned short vert_pixel_count;
+	unsigned char  aspect_ratio;
+	unsigned char  orientation;
+	unsigned char  subpixel_info;
+	unsigned char  horz_pitch;
+	unsigned char  vert_pitch;
+
+	unsigned char  display_color_depth:4;
+	unsigned char  reserved2:4;
+	unsigned char  response_time;
+} display_dev_t;
+
+/* LVDS Interface Timing and Power Sequencing */
+typedef struct _lvds_display {
+	unsigned char  tag;                /* data block type */
+	unsigned char  revision:3;
+	unsigned char  reserved:5;
+	unsigned char  payload;
+
+	unsigned char  max_t1:4;
+	unsigned char  min_t1:4;
+
+	unsigned char  max_t2:6;
+	unsigned char  reserved2:2;
+
+	unsigned char  max_t3:6;
+	unsigned char  reserved3:2;
+
+	unsigned char  min_t4:7;
+	unsigned char  reserved4:1;
+
+	unsigned char  min_t5:6;
+	unsigned char  reserved5:2;
+
+	unsigned char  min_t6:6;
+	unsigned char  reserved6:2;
+} lvds_display_t;
+
+/* Transfer Characteristics Data Block */
+typedef struct _transfer_char {
+	unsigned char  tag;                /* data block type */
+	unsigned char  revision:3;
+	unsigned char  reserved:5;
+	unsigned char  payload;
+	unsigned char  luminance;
+} transfer_char_t;
+
+/* Vendor specific Data Block */
+typedef struct _vendor {
+	unsigned char  tag;                /* data block type */
+	unsigned char  revision:3;
+	unsigned char  reserved:5;
+	unsigned char  payload;
+	unsigned char  vendor_id[3];                /* no NULL char */
+	unsigned char  vendor_specific_data[246];   /* 245 + NULL */
+} vendor_t;
+
+/* Stereo methods */
+#define STEREO_FIELD_SEQUENTIAL      0x00
+#define STEREO_SIDE_BY_SIDE          0x01
+#define STEREO_PIXEL_INTERLEAVED     0x02
+#define STEREO_DUAL_INTERFACE        0x03
+#define STEREO_MULTIVIEW             0x04
+#define STEREO_PROPRIETARY           0xFF
+
+/* Stereo Display Interface Data Block */
+typedef struct _stereo_intf {
+	unsigned char  tag;                /* data block type */
+	unsigned char  revision:3;
+	unsigned char  reserved:5;
+	unsigned char  payload;
+
+	unsigned char  stereo_intf_payload;
+	unsigned char  stereo_intf_method;
+	union {
+		unsigned char  stereo_polarity;     /* Field Sequential Stereo */
+		unsigned char  view_identity;       /* Side-by-side Stereo */
+		unsigned char  pattern8x8[8];       /* Pixel Interleaved Stereo */
+		unsigned char  polarity_mirroring;  /* Dual Interface Stereo */
+		struct {                            /* Multiview stereo */
+			unsigned char  num_views;
+			unsigned char  interleaving_method;
+		} multiview;
+		/* Note: In case of proprietary stereo method, the parameters can be
+		 * somewhere in the Vendor Specific Block */
+		unsigned char  stereo_params[8];
+	};
+} stereo_intf_t;
+
+/* Display Interface Data Block */
+#define INTERFACE_ANALOG    0x0
+#define INTERFACE_LVDS      0x1
+#define INTERFACE_TMDS      0x2
+#define INTERFACE_RSDS      0x3
+#define INTERFACE_DVID      0x4
+#define INTERFACE_DVII_A    0x5
+#define INTERFACE_DVII_D    0x6
+#define INTERFACE_HDMI_A    0x7
+#define INTERFACE_HDMI_B    0x8
+#define INTERFACE_MDDI      0x9
+#define INTERFACE_DISP_PORT 0xA
+#define INTERFACE_PROP_DIG  0xB
+
+/* Interface color depth */
+#define INTERFACE_6BPPC            0x01   /* 6 bits per primary color */
+#define INTERFACE_8BPPC            0x02   /* 8 bits per primary color */
+#define INTERFACE_10BPPC           0x04   /* 10 bits per primary color */
+#define INTERFACE_12BPPC           0x08   /* 12 bits per primary color */
+#define INTERFACE_14BPPC           0x10   /* 14 bits per primary color */
+#define INTERFACE_16BPPC           0x20   /* 16 bits per primary color */
+
+typedef struct _display_intf {
+	unsigned char  tag;                /* data block type */
+	unsigned char  revision:3;
+	unsigned char  reserved:5;
+	unsigned char  payload;
+
+	unsigned char  num_channels:4;
+	unsigned char  intf_type:4;
+
+	unsigned char  intf_revision:4;
+	unsigned char  intf_version:4;
+
+	unsigned char  rgb_color_depth:6;
+	unsigned char  reserved2:2;
+
+	unsigned char  ycbcr_444_color_depth:6;
+	unsigned char  reserved3:2;
+
+	unsigned char  ycbcr_422_color_depth:6;
+	unsigned char  reserved4:2;
+
+	unsigned char  cp_type:3;
+	unsigned char  reserved5:2;
+	unsigned char  color_encoding:3;
+
+	unsigned char  cp_revision:4;
+	unsigned char  cp_version:4;
+
+	unsigned char  ss_percent:4;
+	unsigned char  reserved6:2;
+	unsigned char  ss_type:2;
+
+	union {
+		struct {
+			/* Interface type: LVDS */
+			unsigned char  support_3_3v:1;
+			unsigned char  support_5v:1;
+			unsigned char  support_12v:1;
+			unsigned char  support_2_8v:1;
+			unsigned char  openldi:1;
+			unsigned char  reserved5:3;
+
+			unsigned char  data_strobe:1;
+			unsigned char  de_polarity:1;
+			unsigned char  de_mode:1;
+			unsigned char  reserved6:5;
+		} lvds;
+		struct {
+			/* Interface type: Proprietary Digital Interface */
+			unsigned char  data_strobe:1;
+			unsigned char  de_polarity:1;
+			unsigned char  de_mode:1;
+			unsigned char  reserved7:5;
+
+			unsigned char  reserved8;
+		} pdi;
+		unsigned short bytes9_10;
+	};
+} display_intf_t;
+
+/* Serial Number String */
+typedef struct _serial_number {
+	unsigned char  tag;                /* data block type */
+	unsigned char  revision:3;
+	unsigned char  reserved:5;
+	unsigned char  payload;
+
+	unsigned char  serial_num[249];    /* 248 + NULL */
+} serial_number_t;
+
+/* General Purpose ASCII String */
+typedef struct _general_string {
+	unsigned char  tag;                /* data block type */
+	unsigned char  revision:3;
+	unsigned char  reserved:5;
+	unsigned char  payload;
+
+	unsigned char  string[249];        /* 248 + NULL */
+} general_string_t;
+
+/* This structure holds all of the parsed DisplayID information.*/
+/* 5-required bytes:
+ *  1-byte  - version, revision
+ *  1-byte  - payload
+ *  1-byte  - number of extensions
+ *  1-byte  - product type identifier
+ *  1-byte  - checksum
+ */
+typedef struct _displayid {
+	unsigned char    revision:4;         /* HEADER: revision */
+	unsigned char    version:4;          /* version */
+	unsigned char    payload;            /* payload excluding 5 required bytes*/
+	unsigned char    ptype_id;           /* DisplayID product type identifier */
+	unsigned char    num_extensions;     /* number of extension sections */
+	unsigned char    check_sum;          /* FOOTER: last byte of the section */
+
+	display_params_t display_params;     /* display params block */
+	timing_range_t   timing_range;       /* timing range block */
+	lvds_display_t   lvds;               /* LVDS interface & display block */
+	display_dev_t    display_dev;        /* display device block */
+	display_intf_t   display_intf;       /* display interface block */
+	unsigned char    dummy_db[256];      /* dummy datablock */
+
+	/* Video Timing Modes Type I, II DTDs into pd_timing_t */
+	unsigned char   num_timings;
+	pd_timing_t     timings[DISPLAYID_MAX_NUM_TIMINGS];
+
+	/* DisplayID attributes */
+	unsigned char   num_attrs;
+	pd_attr_t       attr_list[DISPLAYID_MAX_ATTRS];
+
+#ifndef CONFIG_MICRO
+	productid_t      		productid;       /* product id block */
+	color_char_t     		color_char;      /* color characteristics block */
+	serial_number_t  		serial_num;      /* serial number ASCII string */
+	general_string_t 		general_string;  /* general purpose ASCII string */
+	transfer_char_t  		transfer_char;   /* transfer characteristics block */
+	stereo_intf_t    		stereo_intf;     /* stereo display interface */
+	vendor_t 				vendor;          /* vendor specific data */
+	igd_DID_rotation_info_t rotation_info;   /* display orientation data */
+#endif
+} displayid_t;
+
+/* Pack back to default */
+#pragma pack()
+
+/* Functions */
+void displayid_filter_range_timings(pd_timing_t *tt, timing_range_t *range,
+	unsigned char firmware_type);
+int displayid_parse(unsigned char *buffer, displayid_t   *displayid,
+		pd_timing_t *timings, int count, unsigned char upscale);
+
+void displayid_dump(unsigned char *buffer, unsigned short size);
+void displayid_print(unsigned char *buffer, displayid_t *displayid);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/dsp.h b/drivers/gpu/drm/emgd/emgd/include/dsp.h
new file mode 100644
index 0000000..8a803bf
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/dsp.h
@@ -0,0 +1,46 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: dsp.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _DSP_H_
+#define _DSP_H_
+
+#include <mode.h>
+
+/* FIXME: Illegal exports */
+void dsp_dc_init(igd_context_t *context);
+int dsp_alloc(igd_context_t *context, unsigned long dc, unsigned long flags);
+int dsp_wait_rb(igd_context_t *context);
+unsigned long dsp_valid_dc(unsigned long dc, unsigned long flags);
+int dsp_display_connected(igd_context_t *context, igd_display_port_t *port);
+
+
+#endif /* _DSP_H_ */
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/edid.h b/drivers/gpu/drm/emgd/emgd/include/edid.h
new file mode 100644
index 0000000..829e272
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/edid.h
@@ -0,0 +1,130 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: edid.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Header file for EDID.
+ *  Supported EDID versions:
+ *  EDID 1.3 (backward compatible with 1.1, 1.2)
+ *-----------------------------------------------------------------------------
+ */
+
+/*
+ * This is a basic EDID parser. It only parses the parts of the EDID that
+ * are useful for developing timings and identifying the monitor. Items
+ * like monitor serial numbers, chromaticity settings etc. are not useful
+ * in the display drivers. There should be a simple interface to provide
+ * the complete unparsed EDID to IAL, so that such information can be
+ * used by a IAL driver if need be.
+ *
+ * timings_t: This is a structure that contains one set of display timings.
+ *  It is complete in that it contains all 12 timings fields instead of
+ *  the popular 8. Some of the "Established" EDID timings require all 12
+ *  fields. It also allows for both established flags and driver specific
+ *  flags to make it flexible enough to work for most drivers. The
+ *  EDID parser will mark the flags with FB_TIMINGS_PREFERRED if they are
+ *  found to be listed in the EDID. This does not include modes within
+ *  the the sync ranges (if provided), only "Established" "Standard" and
+ *  "Detailed" timings.
+ *
+ * edid_t: This structure will be populated by the EDID parser. There
+ *  are three important areas of information that impact display timings.
+ *  The h_max,h_min,v_max,v_min represent the range of timings that the
+ *  display is capable of accepting. No timings outside this range should
+ *  be used by the driver if a range is provided.
+ *
+ *  Any "Detailed" timings will be fully parsed and returned in
+ *  the timings array (only the first 12 are parsed, it is very unlikely
+ *  that any EDID exist that contain this many).
+ *
+ *  Suggested driver behavior when setting display timings would be to
+ *  first attempt to use "Detailed" timings provided by the monitor. Then
+ *  attempt to use the "Standard" timings that were marked as PREFERRED,
+ *  then as a last alternative, use a nonstandard set of timings within
+ *  the provided range.
+ *
+ */
+
+#ifndef _EDID_H
+#define _EDID_H
+
+#include <displayid.h>
+#include <pd.h>
+
+/* This structure holds all of the parsed EDID information.*/
+#define NUM_TIMINGS 12
+
+/* EDID return values */
+#define EDID_ERROR_PARSE  1
+#define EDID_READ_AGAIN   2
+
+typedef struct _established_timing {
+	unsigned long width;
+	unsigned long height;
+	unsigned long refresh;
+} established_timing_t;
+
+typedef struct _edid {
+	unsigned char     version;            /* Edid Version */
+	unsigned char     revision;           /* Edid Revision */
+	char              vendor[4];          /* Vendor Name code */
+	unsigned long     product_code;       /* Vendor assigned code */
+	unsigned long     serial_number;      /* 32-bit serial number */
+	unsigned char     manf_week;          /* Manufactored week number */
+	unsigned long     manf_year;          /* Manufactored year */
+	unsigned char     standard_color;
+	unsigned char     preferred_timing;   /* Use first timing Provided */
+	unsigned char     dpms;
+	unsigned char     display_type;
+	unsigned char     gtf;
+	unsigned char     range_set;          /* EDID Contains Valid Range Data */
+	timing_range_t    range;
+	unsigned char     num_timings;
+	pd_timing_t       timings[NUM_TIMINGS];
+	char              name[14];
+	cea_extension_t	  *cea;				  /* CEA extension based on 861-B */
+} edid_t;
+
+/* Functions */
+int edid_parse(
+		unsigned char *buffer,
+		edid_t        *edid,
+		pd_timing_t   *timings,
+		int           count,
+		unsigned char upscale);
+
+void enable_disable_timings(pd_timing_t *timing, unsigned char enable);
+void enable_scaled_timings(pd_timing_t *timing, pd_timing_t *dtd,
+	unsigned char upscale);
+void firmware_dump(unsigned char *buffer, unsigned short size);
+void edid_print(edid_t *edid);
+
+int edid_ext_parse(
+		unsigned char *buffer,
+		edid_t        *edid,
+		pd_timing_t   *timings,
+		int           count,
+		unsigned char upscale);
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/general.h b/drivers/gpu/drm/emgd/emgd/include/general.h
new file mode 100644
index 0000000..159bf23
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/general.h
@@ -0,0 +1,84 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: general.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file includes general equates.
+ *  Compiler:
+ *  This file contains general constants, structures and should be included
+ *  in all noninclude files.
+ *-----------------------------------------------------------------------------
+ */
+
+/*===========================================================================
+; General Constants
+;--------------------------------------------------------------------------*/
+
+#ifndef _GENERAL_H_
+#define _GENERAL_H_
+
+#define BIT0  0x00000001L
+#define BIT1  0x00000002L
+#define BIT2  0x00000004L
+#define BIT3  0x00000008L
+
+#define BIT4  0x00000010L
+#define BIT5  0x00000020L
+#define BIT6  0x00000040L
+#define BIT7  0x00000080L
+
+#define BIT8  0x00000100L
+#define BIT9  0x00000200L
+#define BIT10 0x00000400L
+#define BIT11 0x00000800L
+
+#define BIT12 0x00001000L
+#define BIT13 0x00002000L
+#define BIT14 0x00004000L
+#define BIT15 0x00008000L
+
+#define BIT16 0x00010000L
+#define BIT17 0x00020000L
+#define BIT18 0x00040000L
+#define BIT19 0x00080000L
+
+#define BIT20 0x00100000L
+#define BIT21 0x00200000L
+#define BIT22 0x00400000L
+#define BIT23 0x00800000L
+
+#define BIT24 0x01000000L
+#define BIT25 0x02000000L
+#define BIT26 0x04000000L
+#define BIT27 0x08000000L
+
+#define BIT28 0x10000000L
+#define BIT29 0x20000000L
+#define BIT30 0x40000000L
+#define BIT31 0x80000000L
+
+
+#endif // _GENERAL_H_
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/instr_common.h b/drivers/gpu/drm/emgd/emgd/include/instr_common.h
new file mode 100644
index 0000000..95c7e38
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/instr_common.h
@@ -0,0 +1,54 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: instr_common.h
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Common tools for hardware that uses instruction engines.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_INSTR_COMMON_H
+#define _IGD_INSTR_COMMON_H
+
+/* Write instructions macro. */
+#ifdef DEBUG_BUILD_TYPE
+#define INSTR_WRITE(data, addr)											\
+    if(igd_debug->hal.instr) {											\
+		EMGD_DEBUG_S("    addr:%p   data:0x%8.8x", ((void *)(addr)),	\
+			(unsigned int)(data));										\
+    }																	\
+	EMGD_WRITE32 (data, (addr));											\
+	addr++;
+
+#define IGD_PRINT_INSTR(name)                                    \
+    if(igd_debug->hal.instr) {									 \
+		EMGD_DEBUG_S("GMCH Instruction: %s", name);				 \
+    }
+#else
+#define INSTR_WRITE(data, addr) EMGD_WRITE32(data, (addr)++);
+#define IGD_PRINT_INSTR(name)
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/intelpci.h b/drivers/gpu/drm/emgd/emgd/include/intelpci.h
new file mode 100644
index 0000000..b389cc7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/intelpci.h
@@ -0,0 +1,98 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: intelpci.h
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Contains PCI bus transaction definitions
+ *-----------------------------------------------------------------------------
+ */
+
+/* PCI */
+#define PCI_VENDOR_ID_INTEL             0x8086
+#ifndef PCI_VENDOR_ID_STMICRO
+#define PCI_VENDOR_ID_STMICRO           0x104A
+#endif
+
+/* PLB Family Chips */
+#define PCI_DEVICE_ID_BRIDGE_PLB        0x8100
+#define PCI_DEVICE_ID_VGA_PLB           0x8108
+
+/* Atom E6xx */
+#define PCI_DEVICE_ID_BRIDGE_TNC        0x4114
+#define PCI_DEVICE_ID_VGA_TNC           0x4108
+
+/* Atom E6xx ULP */
+#define PCI_DEVICE_ID_BRIDGE_TNC_ULP    0x4115
+
+/* Atom E6xx Device 3 */
+#define PCI_DEVICE_ID_SDVO_TNC 	        0x8182
+
+/* Atom E6xx Device 31 (LPC) */
+#define PCI_DEVICE_ID_LPC_TNC 	        0x8186
+
+/* Atom E6xx ST Micro SDVO PCI device */
+#define PCI_DEVICE_ID_SDVO_TNC_ST       0xcc13
+
+/* Atom E6xx ST Micro GPIO SDVO PCI device */
+#define PCI_DEVICE_ID_SDVO_TNC_ST_GPIO  0xcc0c
+
+/* Support for MSRT and Pre-Release PCI ID for Atom E6xx
+ * Can be removed in future */
+#if 0
+/* Atom E6xx A0 Stepping */
+#define PCI_DEVICE_ID_BRIDGE_TNC_A0     0x4110
+#define PCI_DEVICE_ID_VGA_TNC_A0        0x4100
+
+/* Moorestown */
+#define PCI_DEVICE_ID_BRIDGE_LNC        0x4110
+#define PCI_DEVICE_ID_VGA_LNC           0x4102
+#endif
+
+/* Start: Southbridge specific */
+#define PCI_DEVICE_ID_LPC_82801AA       0x2410
+#define PCI_DEVICE_ID_LPC_82801AB       0x2420
+#define PCI_DEVICE_ID_LPC_82801BA       0x2440
+#define PCI_DEVICE_ID_LPC_82801BAM      0x244c
+#define PCI_DEVICE_ID_LPC_82801E        0x2450
+#define PCI_DEVICE_ID_LPC_82801CA       0x2480
+#define PCI_DEVICE_ID_LPC_82801DB       0x24c0
+#define PCI_DEVICE_ID_LPC_82801DBM      0x24cc
+#define PCI_DEVICE_ID_LPC_82801EB       0x24d0
+#define PCI_DEVICE_ID_LPC_82801EBM      0x24dc
+#define PCI_DEVICE_ID_LPC_80001ESB      0x25a1  /* LPC on HanceRapids ICH */
+#define PCI_DEVICE_ID_LPC_82801FB       0x2640  /* ICH6/ICH6R */
+#define PCI_DEVICE_ID_LPC_82801FBM      0x2641  /* ICH6M/ICH6MR */
+#define PCI_DEVICE_ID_LPC_82801FW       0x2642  /* ICH6W/ICH6WR */
+#define PCI_DEVICE_ID_LPC_82801FWM      0x2643  /* ICH6MW/ICH6MWR */
+#define PCI_DEVICE_ID_LPC_Q35DES        0x2910  /* ICH9 */
+#define PCI_DEVICE_ID_LPC_Q35DHES       0x2912  /* ICH9 */
+#define PCI_DEVICE_ID_LPC_Q35DOES       0x2914  /* ICH9 */
+#define PCI_DEVICE_ID_LPC_Q35RES        0x2916  /* ICH9 */
+#define PCI_DEVICE_ID_LPC_Q35BES        0x2918  /* ICH9 */
+
+
+
+#define INTEL_PTE_ALLIGNMENT                0xFFFFF000
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/math_fix.h b/drivers/gpu/drm/emgd/emgd/include/math_fix.h
new file mode 100644
index 0000000..91306fe
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/math_fix.h
@@ -0,0 +1,59 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: math_fix.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains OS abstracted interfaces to fixed point math functions
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OAL_MATH_FIX_H
+#define _OAL_MATH_FIX_H
+
+
+#define OS_POW_FIX(b, p)         os_pow_fix(b, p)
+
+
+#define OS_MAX(a,b)              (((a) > (b)) ? (a) : (b))
+#define OS_MIN(a,b)              (((a) < (b)) ? (a) : (b))
+
+/*****************************************************************************
+ * Function: os_pow_fix
+ *
+ * Parameters:
+ *    [IN] base:  the base, should be between 0 and 255.
+ *    [IN] power:  this must be in 24i.8f format.
+ *
+ * Description:
+ *    This function uses the Taylor Series to approximate the power function
+ *    using fixed-point math.
+ *
+ ****************************************************************************/
+
+unsigned int os_pow_fix( const int base, const int power );
+
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/memlist.h b/drivers/gpu/drm/emgd/emgd/include/memlist.h
new file mode 100644
index 0000000..7d9fa22
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/memlist.h
@@ -0,0 +1,154 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: memlist.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 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;
+	unsigned long used;
+	/* The number of bytes of memory requested/allocated for this chunk */
+	unsigned long size;
+	/* The number of pages of memory required for "size" bytes */
+	unsigned long pages;
+	/* A boolean flag indicating if the chunk's memory has been bound by AGP */
+	unsigned long bound;
+	/* Either AGP_PHYS_MEMORY or AGP_NORMAL_MEMORY */
+	unsigned long type;
+	gmm_mem_buffer_t *gtt_mem;
+	void *addr;
+	unsigned long ref_cnt;
+	/* An array of page addresses (created by gmm_get_page_list() */
+	unsigned long *page_addresses;
+} gmm_chunk_t;
+
+typedef struct _gmm_context_t {
+	unsigned long max_mem;
+	gmm_chunk_t *head_chunk;
+	gmm_chunk_t *tail_chunk;
+	igd_memstat_t memstat;
+	igd_context_t *context;
+	igd_gtt_info_t *gtt;
+} gmm_context_t;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/memory.h b/drivers/gpu/drm/emgd/emgd/include/memory.h
new file mode 100644
index 0000000..f85477c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/memory.h
@@ -0,0 +1,421 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: memory.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains OS abstracted interfaces to common memory operations.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OAL_MEMORY_H
+#define _OAL_MEMORY_H
+
+#include <linux/slab.h>
+
+unsigned long os_gart_alloc_page( void );
+unsigned long os_gart_virt_to_phys( unsigned char *a );
+void os_gart_free_page( unsigned char *a );
+
+/* #define INSTRUMENT_KERNEL_ALLOCS */
+#ifdef INSTRUMENT_KERNEL_ALLOCS
+#define MAX_FUNC_NAME 64
+
+typedef struct _os_allocd_mem {
+	void *ptr;
+	unsigned int size;
+	char function[MAX_FUNC_NAME];
+	struct _os_allocd_mem *next;
+} os_allocd_mem;
+
+extern os_allocd_mem *list_head;
+extern os_allocd_mem *list_tail;
+
+static inline void *_os_alloc(unsigned int size, const char *function) {
+	os_allocd_mem *mem;
+	void *ptr = kmalloc(size, GFP_KERNEL);
+	printk(KERN_DEBUG "%s OS_ALLOC(size=%u)=0x%p\n", function, size, ptr);
+	mem = kmalloc(sizeof(os_allocd_mem), GFP_KERNEL);
+	if (!ZERO_OR_NULL_PTR(mem)) {
+		mem->ptr = ptr;
+		mem->size = size;
+		strncpy(mem->function, function, MAX_FUNC_NAME);
+		mem->function[MAX_FUNC_NAME-1] = '\0';
+		mem->next = NULL;
+		if (NULL == list_tail) {
+			list_head = mem;
+		} else {
+			list_tail->next = mem;
+		}
+		list_tail = mem;
+	}
+	return ptr;
+}
+
+static inline void _os_free(void *ptr, const char *function) {
+	printk(KERN_DEBUG "%s OS_FREE(0x%p)\n", function, ptr);
+	if (NULL != list_head) {
+		os_allocd_mem *mem = list_head;
+		os_allocd_mem *prev = NULL;
+		while (NULL != mem) {
+			if (mem->ptr == ptr) {
+				if (mem == list_head) {
+					list_head = mem->next;
+					if (mem == list_tail) {
+						list_tail = NULL;
+					}
+				} else {
+					prev->next = mem->next;
+					if (mem == list_tail) {
+						list_tail = prev;
+					}
+				}
+				kfree(mem);
+				break;
+			}
+			prev = mem;
+			mem = mem->next;
+		}
+	}
+	kfree(ptr);
+}
+
+static inline void emgd_report_unfreed_memory(void) {
+	os_allocd_mem *mem = list_head;
+	os_allocd_mem *prev;
+
+	printk(KERN_DEBUG "%s() REPORT ON NON-FREED MEMORY:\n", __FUNCTION__);
+	while (NULL != mem) {
+		printk(KERN_DEBUG "  addr=0x%p, size=%u, function=\"%s\"\n",
+				mem->ptr, mem->size, mem->function);
+		prev = mem;
+		mem = mem->next;
+		kfree(prev);
+	}
+}
+
+
+/*!
+ * void *OS_ALLOC(size_t size)
+ *
+ * OS_ALLOC is used by OS independent code to allocate system memory and
+ * return a CPU writeable address to the allocated memory (Virtual address)
+ * The returned address has no guarenteed alignment.
+ * size should be <= 4k for larger sizes use OS_ALLOC_LARGE().
+ *
+ * Allocations returned from OS_ALLOC() should be freed with OS_FREE().
+ *
+ * All Full OAL implementations must implement the _OS_ALLOC entry point
+ * to enable use of this function.
+ *
+ * @return NULL on Failure
+ * @return Virtual or Flat address on Success
+ */
+#define OS_ALLOC(a) _os_alloc(a, __FUNCTION__)
+
+/*!
+ * void OS_FREE(void *p)
+ * OS_FREE should be used to free allocations returned from OS_ALLOC()
+ *
+ * All Full OAL implementations must implement the _OS_FREE entry point
+ * to enable use of this function.
+ */
+#define OS_FREE(a) _os_free(a, __FUNCTION__)
+
+/*!
+ * void *OS_ALLOC_LARGE(size_t size)
+ *
+ * OS_ALLOC_LARGE is used by OS independent code to allocate system memory
+ * in the same manner as OS_ALLOC except that size must be > 4k.
+ *
+ * Allocations returned from OS_ALLOC_LARGE() should be freed with
+ * OS_FREE_LARGE().
+ *
+ * All Full OAL implementations must implement the _OS_ALLOC_LARGE entry point
+ * to enable use of this function. This entry point may be implemented
+ * exactly the same as _OS_ALLOC is no diferentiation is required.
+ *
+ * @return NULL on Failure
+ * @return Virtual or Flat address on Success
+ */
+#define OS_ALLOC_LARGE(a) _os_alloc(a, __FUNCTION__)
+
+/*!
+ * void OS_FREE_LARGE(void *p)
+ * OS_FREE_LARGE should be used to free allocations returned from
+ * OS_ALLOC_LARGE()
+ *
+ * All Full OAL implementations must implement the _OS_FREE_LARGE entry point
+ * to enable use of this function. This entry point may be implemented
+ * exactly the same as _OS_FREE is no diferentiation is required.
+ *
+ */
+#define OS_FREE_LARGE(a) _os_free(a, __FUNCTION__)
+
+#else /* INSTRUMENT_KERNEL_ALLOCS */
+
+#define OS_ALLOC(a) kmalloc((a), GFP_KERNEL)
+#define OS_FREE(a) kfree(a)
+#define OS_ALLOC_LARGE(a) kmalloc((a), GFP_KERNEL)
+#define OS_FREE_LARGE(a) kfree(a)
+
+#endif /* INSTRUMENT_KERNEL_ALLOCS */
+
+#define OS_ALLOC_PAGE() NULL
+/*!
+ * void *OS_VIRT_TO_PHYS( void *p )
+ *
+ * OS_VIRT_TO_PHYS is used by OS independent code to obtain the physical
+ * address referenced by the virtual address p. The virtual address must be
+ * one returned by OS_ALLOC_PAGE or OS_ALLOC_CONTIGUOUS.
+ *
+ * This entry point is OPTIONAL. Only OAL implementations that have
+ * implemented the _OS_ALLOC_PAGE or _OS_ALLOC_CONTIGUOUS macros need
+ * implement the _OS_VIRT_TO_PHYS macro. OS independent code that must
+ * function on all implementation may not use this entry point.
+ *
+ * @returns Physical Address
+ */
+#define OS_VIRT_TO_PHYS(a) os_gart_virt_to_phys(a)
+
+/*!
+ * void OS_FREE_PAGE(void *p)
+ * OS_FREE_PAGE should be used to free allocations returned from
+ * OS_ALLOC_PAGE()
+ *
+ * This entry point is OPTIONAL. Only OAL implementations that have implemented
+ * the _OS_ALLOC_PAGE macro need implement the _OS_FREE_PAGE macro.
+ */
+#define OS_FREE_PAGE(a) os_gart_free_page(a)
+
+#define OS_MEMSET(a,b,c) memset(a,b,c)
+#define OS_MEMCPY(a,b,c) memcpy(a,b,c)
+#define OS_MEMCMP(a,b,c) memcmp(a,b,c)
+
+#define OS_OFFSETOF(t,m) offsetof(t,m)
+
+
+/*
+ * void *OS_MEMSET(void *s, int c, size_t n)
+ *
+ * OS_MEMSET sets all bytes of the memory area referenced by address s and
+ * size n to the char value c.
+ *
+ * ALL Full OAL implementations must implement the entry point _OS_MEMSET
+ * to enable use of this function.
+ *
+ * @returns Address s
+ */
+#ifndef OS_MEMSET
+#define OS_MEMSET(a,b,c) _oal_memset(a,b,c)
+#endif
+
+/*
+ * void *OS_MEMCPY(void *dest, void *src, size_t n)
+ *
+ * OS_MEMCPY copies n bytes from the memory referenced by src to the
+ * memory referenced by dest. The areas may not overlap.
+ *
+ * ALL Full OAL implementations must implement the entry point _OS_MEMCPY
+ * to enable use of this function.
+ *
+ * @returns Address dest
+ */
+#ifndef OS_MEMCPY
+#define OS_MEMCPY(a,b,c) _oal_memcpy(a,b,c)
+#endif
+
+/*
+ * void *OS_MEMCMP(void *s1, void *s2, size_t n)
+ *
+ * OS_MEMCMP compares n bytes from the memory referenced by s1 to the
+ * corresponding bytes referenced by s2.
+ *
+ * This entry point is available in all full OAL implementations. An OAL
+ * may implement _OS_MEMCMP macro or the built-in version will be used.
+ *
+ * @returns < 0 if the s1 value is less than s2
+ * @returns > 0 if the s1 value is greater than s2
+ * @returns 0 if the values are equal
+ */
+#ifndef OS_MEMCMP
+#define OS_MEMCMP(a,b,c) _oal_memcmp(a,b,c)
+#endif
+
+
+/*
+ * void *OS_MEMZERO(void *s, size_t n)
+ *
+ * OS_MEMZERO sets all bytes of the memory area referenced by address s and
+ * size n to 0.
+ *
+ * This entry point is available in all full OAL implementations. An OAL
+ * may implement _OS_MEMZERO macro or the built-in version making use of
+ * of _OS_MEMSET will be used.
+ *
+ * @returns Address s
+ */
+#ifndef OS_MEMZERO
+#define OS_MEMZERO(a,b)  OS_MEMSET(a, 0, b)
+#endif
+
+/*
+ * void *OS_MEMZERO(void *s, size_t n)
+ *
+ * OS_MEMZERO sets all bytes of the memory area referenced by address s and
+ * size n to 0.
+ *
+ * This entry point is available in all full OAL implementations. An OAL
+ * may implement _OS_MEMZERO macro or the built-in version making use of
+ * of _OS_MEMSET will be used.
+ *
+ * @returns Address s
+ */
+#ifndef OS_STRNCPY
+#define OS_STRNCPY(d, s, n)  _oal_strncpy(d, s, n)
+#endif
+
+
+
+
+
+/*!
+ * void *OS_ALLOC_CONTIGUOUS( size_t n, size_t align )
+ *
+ * OS_ALLOC_CONTIGUOUS is used by OS independent code to allocate a number
+ * of aligned system memory pages and return a CPU writeable address to the
+ * allocated memory (Virtual address) The returned address must point to
+ * physically contiguous memory aligned to the requested alignment.
+ *
+ * Allocations returned from OS_ALLOC_CONTIGUOUS() should be freed with
+ * OS_FREE_CONTIGUOUS().
+ *
+ * This entry point is OPTIONAL. Only OAL implementations that have the
+ * ability to allocate such pages need implement the _OS_ALLOC_CONTIGUOUS
+ * macro. OS independent code that must function on all implementation may
+ * not use this entry point.
+ *
+ * @return NULL on Failure
+ * @return Virtual or Flat address on Success
+ */
+#define OS_ALLOC_CONTIGUOUS(a,b) _OS_ALLOC_CONTIGUOUS(a,b)
+/*!
+ * void OS_FREE_CONTIGUOUS(void *p)
+ * OS_FREE_CONTIGUOUS should be used to free allocations returned from
+ * OS_ALLOC_CONTIGUOUS()
+ *
+ * This entry point is OPTIONAL. Only OAL implementations that have implemented
+ * the _OS_ALLOC_CONTIGUOUS macro need implement the _OS_FREE_CONTIGUOUS macro.
+ */
+#define OS_FREE_CONTIGUOUS(a) _OS_FREE_CONTIGUOUS(a)
+
+/*!
+ * size_t OS_OFFSETOF(type, member)
+ *
+ * OS_OFFSETOF is used by OS independent code to obtain the offset of a
+ * given member within a type.
+ *
+ * @returns size_t of the offset of member m within type t
+ */
+#ifndef OS_OFFSETOF
+#define OS_OFFSETOF(t,m) ((size_t)&(((t *)0)->m))
+#endif
+
+/*
+ * This is a OS independent helper is case the operating environment
+ * does not supply a memcmp() function. The OAL may use this implementation.
+ */
+static __inline int _oal_memcmp(const void *s1, const void *s2, unsigned long n)
+{
+	const unsigned char *cs1 = (const unsigned char *) s1;
+	const unsigned char *cs2 = (const unsigned char *)s2;
+
+	for ( ; n-- > 0; cs1++, cs2++) {
+		if (*cs1 != *cs2) {
+			return *cs1 - *cs2;
+		}
+	}
+	return 0;
+}
+
+static __inline void *_oal_memcpy(void *dest, const void *src, size_t n)
+{
+	size_t i;
+
+	i=0;
+	while( i < n ) {
+		((unsigned char *)dest)[i] = ((unsigned char *)src)[i];
+		i++;
+	}
+	return dest;
+}
+
+static __inline char *_oal_strncpy(char *dest, const char *src, size_t n)
+{
+	size_t i;
+
+	for(i=0; i<n; i++) {
+		if(!(dest[i] = src[i])) {
+			for(i=i; i<n; i++) {
+				dest[i] = '\0';
+			}
+			return dest;
+		}
+	}
+	return dest;
+}
+
+static __inline void *_oal_memset(void *s, int c, size_t n)
+{
+	unsigned int i;
+	for(i=0; i<n; i++) {
+		((unsigned char *)s)[i] = (unsigned char)c;
+	}
+	return s;
+}
+
+/*
+ * These macros are optional for the OAL port. They are used to do memory
+ * management for virtual apterture space process.
+ */
+
+#ifdef _OS_MAP_STOLEN_MEM
+#define OS_MAP_STOLEN_MEM(a, b, c)        _OS_MAP_STOLEN_MEM(a, b, c)
+#else
+#define OS_MAP_STOLEN_MEM(a, b, c)        0
+#endif
+
+#ifdef _OS_VIRT_APERT_AVAILABLE
+#define OS_VIRT_APERT_AVAILABLE()         _OS_VIRT_APERT_AVAILABLE()
+#else
+#define OS_VIRT_APERT_AVAILABLE()         0
+#endif
+
+#ifdef _OS_GET_VIRT_APERT_BASE
+#define OS_GET_VIRT_APERT_BASE()          _OS_GET_VIRT_APERT_BASE()
+#else
+#define OS_GET_VIRT_APERT_BASE()          NULL
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/mode.h b/drivers/gpu/drm/emgd/emgd/include/mode.h
new file mode 100644
index 0000000..1cb8a2c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/mode.h
@@ -0,0 +1,444 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mode.h
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Contain header information for set mode support
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _MODE_H_
+#define _MODE_H_
+
+/* IO.h is needed for the FAR define */
+#include <io.h>
+
+#include <igd_init.h>
+#include <igd_mode.h>
+#include <general.h>
+#include <context.h>
+#include <cmd.h>
+#include <pd.h>
+#include <edid.h>
+#include <displayid.h>
+#include <igd_render.h>
+
+/* KMS-related Headers */
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_fb_helper.h>
+
+
+#ifndef TRUE
+#define TRUE  1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define IGD_INVALID_MODE 0
+
+/*****************/
+/* Plane Features */
+/*****************/
+#define IGD_PLANE_FEATURES_MASK      0x000000FF
+#define IGD_PLANE_DISPLAY            0x00000001
+#define IGD_PLANE_OVERLAY            0x00000002
+#define IGD_PLANE_SPRITE             0x00000004
+#define IGD_PLANE_CURSOR             0x00000008
+#define IGD_PLANE_VGA                0x00000010
+#define IGD_PLANE_DOUBLE             0x00000020
+/*#define IGD_PLANE_CLONE            0x00000040 currently unused */
+#define IGD_PLANE_DIH                0x00000080
+#define IGD_PLANE_USE_PIPEA          0x00000100
+#define IGD_PLANE_USE_PIPEB          0x00000200
+
+/*****************/
+/* Pipe Features */
+/*****************/
+/* pipe's supported features */
+#define IGD_PIPE_FEATURES_MASK       0x000000FF
+#define IGD_PIPE_DOUBLE              0x00000001
+/* the following 2 bits are not pipe features but
+ * pipe identification bits that share the same
+ * pipe_features variable of the pipe structure
+ * NOTE that these bit-wise OR flags in nibble-2
+ * are also used in the port_features variable
+ * of the port structure (same locations) but
+ * called IGD_PORT_USE_PIPEX
+ */
+#define IGD_PIPE_IS_PIPEA            0x00000100
+#define IGD_PIPE_IS_PIPEB            0x00000200
+
+/*******************/
+/* Cursor Features */
+/*******************/
+/*
+ * Cursor's supported features
+ */
+/*
+ * cursor's pipe usage regulations. These are copies of the PIPE_IS_ bits so
+ * that a quick (pipe_features & plane_features & MASK) will tell you if
+ * the pipe can be used.
+ */
+#define IGD_CURSOR_USE_PIPE_MASK       0x00000F00
+#define IGD_CURSOR_USE_PIPEA           IGD_PIPE_IS_PIPEA
+#define IGD_CURSOR_USE_PIPEB           IGD_PIPE_IS_PIPEB
+
+/*****************/
+/* Port features */
+/*****************/
+/*
+ * Port's supported features
+ *
+ * port features also uses IGD_PORT_SHARE_MASK thus port feature bits
+ * cannot collide with IGD_PORT_SHARE_MASK
+ */
+#define IGD_PORT_FEATURES_MASK       0x000000FF
+#define IGD_RGBA_COLOR               0x00000001
+#define IGD_RGBA_ALPHA               0x00000002
+#define IGD_VGA_COMPRESS             0x00000004 /* Compress VGA to 640x480 */
+#define IGD_PORT_GANG                0x00000008
+/*
+ * port's pipe usage regulations. These are copies of the PIPE_IS_ bits so
+ * that a quick (pipe_features & port_features & MASK) will tell you if
+ * the pipe can be used.
+ */
+#define IGD_PORT_USE_PIPE_MASK       0x00000F00
+#define IGD_PORT_USE_PIPE_MASK_SHIFT 8
+#define IGD_PORT_USE_PIPEA           IGD_PIPE_IS_PIPEA
+#define IGD_PORT_USE_PIPEB           IGD_PIPE_IS_PIPEB
+/*
+ * Ports Sharing information. The port in question can share a pipe with the
+ * listed ports. If a shares with b, b must share with a too.
+ * Must be the same as IGD_PORT_MASK = 0x3f000
+ */
+#define IGD_PORT_SHARE_MASK          IGD_PORT_MASK
+#define IGD_PORT_SHARE_ANALOG        IGD_PORT_ANALOG
+#define IGD_PORT_SHARE_DIGITAL       IGD_PORT_DIGITAL
+#define IGD_PORT_SHARE_LVDS          IGD_PORT_LVDS
+#define IGD_PORT_SHARE_TV            IGD_PORT_TV
+
+/* MAX rings, planes and ports connected to a pipe */
+#define IGD_MAX_PIPE_QUEUES      4
+#define IGD_MAX_PIPE_PLANES      5
+#define IGD_MAX_PIPE_DISPLAYS    4
+#define IGD_MAX_PIPES            2
+#define MAX_DISPLAYS             IGD_MAX_DISPLAYS /* From igd_mode.h */
+
+/* Parameters to mode_update_plane_pipe_ports */
+#define MODE_UPDATE_PLANE  0x1
+#define MODE_UPDATE_PIPE   0x2
+#define MODE_UPDATE_PORT   0x4
+#define MODE_UPDATE_NONE   0x0
+
+#define PLANE(display) \
+	((igd_display_plane_t *)(((igd_display_context_t *)display)->plane))
+#define PIPE(display)  \
+	((igd_display_pipe_t *)(((igd_display_context_t *)display)->pipe))
+#define PORT(display, pn)  \
+	((igd_display_port_t *)(((igd_display_context_t *)display)->port[pn-1]))
+#define PORT_OWNER(display)  \
+	((igd_display_port_t *)(((igd_display_context_t *)display)->port[display->port_number-1]))
+
+#define MODE_IS_SUPPORTED(t) (t->mode_info_flags & IGD_MODE_SUPPORTED)
+#define MODE_IS_VGA(t) \
+	((((pd_timing_t *)t)->mode_info_flags & IGD_MODE_VESA) &&	\
+		(t->mode_number < 0x1D))
+
+#define IGD_KMS_PIPEA (IGD_PIPE_IS_PIPEA >> IGD_PORT_USE_PIPE_MASK_SHIFT)
+#define IGD_KMS_PIPEB (IGD_PIPE_IS_PIPEB >> IGD_PORT_USE_PIPE_MASK_SHIFT)
+
+#define KMS_PIPE_FEATURES(display) \
+	(((igd_display_pipe_t *)((igd_display_context_t *)display)->pipe)->pipe_features)
+
+#define KMS_PIPE_ID(pipe_features) \
+	((pipe_features & IGD_PORT_USE_PIPE_MASK) >> IGD_PORT_USE_PIPE_MASK_SHIFT)
+
+
+/* #define DC_PORT_NUMBER(dc, i) ((dc >> (i * 4)) & 0x0f) */
+#define DC_PORT_NUMBER IGD_DC_PORT_NUMBER
+
+/* This structure is used for the mode table which is a list of all
+ * supported modes. */
+
+typedef pd_timing_t igd_timing_info_t, *pigd_timing_info_t;
+
+
+/*
+ * NOTE: The plane typedef is a generic type. Each plane type has an
+ * equivalent typedef that is more specific to the type of plane. They
+ * MUST remain equivalent. If you change one you must change them all.
+ */
+typedef struct _igd_plane {
+	unsigned long plane_reg;       /* plane control register */
+	unsigned long plane_features;  /* plane feature list */
+	int           inuse;           /* plane inuse ? */
+	int           ref_cnt;         /* # of displays using this plane */
+	unsigned long *pixel_formats;  /* supported pixel formats */
+	void *plane_info;              /* ptr to plane_info */
+	struct _igd_plane *mirror;     /* pointer to mirror plane */
+} igd_plane_t;
+
+typedef struct _igd_display_plane {
+	unsigned long plane_reg;         /* plane contron register */
+	unsigned long plane_features;    /* list of plane features */
+	int           inuse;             /* plane inuse ? */
+	int           ref_cnt;           /* # of displays using this plane */
+	unsigned long *pixel_formats;    /* list of pixel formats supported */
+	igd_framebuffer_info_t *fb_info; /* attached fb to this plane */
+	struct _igd_display_plane *mirror;  /* pointer to mirror plane */
+} igd_display_plane_t, *pigd_display_plane_t;
+
+typedef struct _igd_cursor {
+	unsigned long cursor_reg;        /* cursor control register */
+	unsigned long plane_features;    /* cursor plane features */
+	int           inuse;             /* is this cursor in use? */
+	int           ref_cnt;           /* # of displays using this plane */
+	unsigned long *pixel_formats;    /* list of pixel_formats supported */
+	igd_cursor_info_t *cursor_info;
+	struct _igd_cursor *mirror;  /* pointer to mirror plane */
+} igd_cursor_t;
+
+typedef struct _igd_clock {
+	unsigned long dpll_control;     /* DPLL control register */
+	unsigned long mnp;              /* FPx0 register */
+	unsigned long p_shift;          /* Bit location of P within control */
+	unsigned long actual_dclk;		/* Actual dotclock after calculating dpll */
+}igd_clock_t;
+
+typedef struct _igd_display_pipe {
+	unsigned long pipe_num;             /* 0 Based index */
+	unsigned long pipe_reg;             /* pipe configuration register */
+	unsigned long timing_reg;           /* timing register(htotal) */
+	unsigned long palette_reg;          /* palette register */
+	igd_clock_t   *clock_reg;           /* DPLL clock registers */
+	unsigned long pipe_features;        /* pipe features */
+	int           inuse;                /* pipe allocated? TRUE/FALSE */
+	int           ref_cnt;              /* # of displays using this pipe */
+	cmd_queue_t *queue[IGD_MAX_PIPE_QUEUES]; /* Queues for this pipe */
+	igd_display_plane_t   *plane;      /* dsp plane connected to pipe */
+	igd_cursor_t          *cursor;     /* cursor connected to this pipe */
+	void                  *sprite;     /* sprite connected to this pipe */
+	igd_timing_info_t     *timing;     /* current timings on the port */
+	igd_display_context_t *owner;      /* owner display of this pipe */
+	unsigned long dclk;                /* current dclk running on this pipe */
+}igd_display_pipe_t, *pigd_display_pipe_t;
+
+typedef struct _igd_display_port {
+	unsigned long port_type;            /* port type */
+	unsigned long port_number;          /* port number */
+	char          port_name[8];         /* port name DVO A, B, C, LVDS, ANALOG */
+	unsigned long port_reg;             /* port control register */
+	unsigned long i2c_reg;              /* GPIO pins for i2c on this port */
+	unsigned long dab;                  /* i2c Device Address Byte */
+	unsigned long ddc_reg;              /* GPIO pins for DDC on this port */
+	unsigned long ddc_dab;
+	unsigned long port_features;        /* port features */
+	unsigned long clock_bits;           /* Clock input to use */
+	int           inuse;                /* port is in use */
+	unsigned long  power_state;         /* D Power state for the display/port */
+	unsigned long bl_power_state;       /* D Power state for the FP backlight */
+	struct _igd_display_port *mult_port;/* pointer to multiplexed port,
+										 * if it is used in that way */
+	igd_display_info_t    *pt_info;     /* port timing info */
+	pd_driver_t           *pd_driver;
+	void                  *pd_context;  /* Context returned from PD */
+	pd_callback_t         *callback;    /* DD Callback to passed to PD */
+	unsigned long         num_timing;   /* number of timings available */
+	igd_timing_info_t     *timing_table; /* static/dynamic PD timings list */
+	unsigned long         i2c_speed;    /* Connected encoder's I2C bus speed */
+	unsigned long         ddc_speed;    /* DDC speed in KHz */
+	igd_param_fp_info_t   *fp_info;     /* Flat panel parameter info if any */
+	igd_param_dtd_list_t  *dtd_list;    /* EDID-less DTD info if any */
+	igd_param_attr_list_t *attr_list;   /* Saved attributes if any */
+	igd_attr_t            *tmp_attr;    /* Temp attr array, for copying */
+	unsigned int          tmp_attr_num; /* Number of attr in temp array */
+	igd_timing_info_t     *fp_native_dtd; /* FP native DTD */
+	unsigned long         pd_type;      /* Display type given by port driver */
+	unsigned long         pd_flags;     /* port driver flags */
+	unsigned long         saved_bl_power_state;
+
+	/* This attribute list is designed to eventually suck in things above
+	 * such as fb_info.  For now, it only has color correction attributes */
+	igd_attr_t            *attributes;
+
+	unsigned char         firmware_type;
+	union {
+		displayid_t       *displayid;
+		edid_t            *edid;         /* EDID information */
+	};
+
+    /* Added for VBIOS size Reduction */
+	unsigned long         preserve;
+	unsigned long         mult_preserve;
+	unsigned long         vga_sync;
+
+}igd_display_port_t, *pigd_display_port_t;
+
+/* This structure is used to save mode state.
+ * Rightnow, it is saving state of current port and its port driver state.
+ * This information is used while restoring to a previously saved mode
+ * state.
+ * TODO: This can be extended to save all display modules (mode, dsp, pi) reg
+ * information along with port driver's state information. This requires
+ * changes to exiting reg module. */
+#define MAX_PORT_DRIVERS     20
+typedef struct _mode_pd_state {
+		igd_display_port_t *port;       /* display port */
+		void               *state;      /* and its port driver state */
+} mode_pd_state_t;
+
+typedef struct _mode_state_t {
+	mode_pd_state_t pd_state[MAX_PORT_DRIVERS];
+} mode_state_t;
+
+
+/**
+ * This holds information about a framebuffer
+ */
+typedef struct _emgd_framebuffer {
+	struct drm_framebuffer base;
+	enum {
+		GMM_FRAMEBUFFER,
+		PVR_FRAMEBUFFER
+	} type;
+	void *pvr_meminfo;
+	struct page **pagelist;
+	unsigned long gtt_offset;
+	unsigned long handle;
+} emgd_framebuffer_t;
+
+typedef struct _emgdfb_par {
+        struct drm_device  *dev;
+        emgd_framebuffer_t *emgd_fb;
+} emgdfb_par_t;
+
+
+/**
+ * This holds information about a CRTC.
+ */
+typedef struct _emgd_crtc {
+        struct drm_crtc         base;
+
+		/* Spinlock to protect access to this structure */
+		spinlock_t              crtc_lock;
+
+        int                     crtc_id;
+        igd_display_pipe_t     *igd_pipe;
+        emgd_framebuffer_t     *fbdev_fb;
+        struct drm_mode_set     mode_set;
+        struct drm_display_mode saved_mode;
+        struct drm_display_mode saved_adjusted_mode;
+        unsigned char           lut_r[256];
+        unsigned char           lut_g[256];
+        unsigned char           lut_b[256];
+        unsigned char           lut_a[256];
+
+		/* Flip request work task */
+		struct work_struct      flip_work;
+		unsigned char           flip_work_queued;
+
+		/*
+		 * Framebuffer that we're in the process of flipping to (may not
+		 * actually show up until rendering is complete, the actual
+		 * registers are programmed, and a vblank happens).
+		 */
+		emgd_framebuffer_t *newfb;
+
+		/*
+		 * Target for rendering completion to allow flip to proceed.
+		 * Rendering operations may continue to be dispatched against this
+		 * FB after the flip ioctl is called, so we need to track the
+		 * number of pending operations at the point the ioctl was called
+		 * and use that as our target to flip on.
+		 */
+		unsigned long render_complete_at;
+
+		/*
+		 * Are we waiting for the next vblank event to perform flip cleanup
+		 * on this CRTC?  Flip cleanup primarily involves sending a
+		 * notification event back to userspace.
+		 */
+		unsigned char vblank_expected;
+
+		/* Userspace event to send back upon flip completion. */
+		struct drm_pending_vblank_event *flip_event;
+} emgd_crtc_t;
+
+
+/**
+ * This holds information about an individual encoder
+ *  */
+typedef struct _emgd_encoder {
+        struct drm_encoder base;
+
+        unsigned long       crtc_mask;
+        unsigned long       clone_mask;
+        igd_display_port_t *igd_port;
+        mode_pd_state_t     state;
+        /* flags is a bit mask. For information
+         * on the different masks, see ENCODER_FLAG_xx
+         */
+		unsigned long       flags;
+} emgd_encoder_t;
+
+#define ENCODER_FLAG_FIRST_DPMS  0x1
+#define ENCODER_FLAG_FIRST_ALTER 0x2
+#define ENCODER_FLAG_SEAMLESS    0x4
+
+/**
+ *  * This holds information about an individual output
+ *   */
+typedef struct _emgd_connector {
+        struct drm_connector  base;
+
+        emgd_encoder_t       *encoder;
+        unsigned long         type;
+        struct drm_property **properties;
+        unsigned long         num_of_properties;
+
+        struct _drm_emgd_private *priv;
+} emgd_connector_t;
+
+/**
+ *  * This holds information on our framebuffer device.
+ *   */
+typedef struct _emgd_fbdev {
+        struct drm_fb_helper      helper;
+
+        emgd_framebuffer_t       *emgd_fb;
+        u32                       pseudo_palette[17];
+        struct list_head          fbdev_list;
+        struct _drm_emgd_private *priv;
+} emgd_fbdev_t;
+
+
+
+
+#endif // _IGD_MODE_H_
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/mode_access.h b/drivers/gpu/drm/emgd/emgd/include/mode_access.h
new file mode 100644
index 0000000..307739a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/mode_access.h
@@ -0,0 +1,52 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mode_access.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Contains functional support to set video mode
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_MODEACCESS_H
+#define _IGD_MODEACCESS_H
+
+#include <mode.h>
+#include <context.h>
+
+extern int mode_getresolution(igd_display_h display_h,
+	unsigned long *width,
+	unsigned long *height);
+
+/*
+ * The power state for the display is the lower(power) of the display
+ * state and the device state. A larger power_state number means a
+ * lower power state.
+ */
+#define GET_DISPLAY_POWER_STATE(d_h, pn) \
+(GET_DEVICE_POWER_STATE(d_h) > ((PORT(d_h, pn))->power_state) ? \
+GET_DEVICE_POWER_STATE(d_h) : ((PORT(d_h, pn))->power_state))
+
+#endif /* _IGD_MODEACCESS_H */
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/module_init.h b/drivers/gpu/drm/emgd/emgd/include/module_init.h
new file mode 100644
index 0000000..8feafea
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/module_init.h
@@ -0,0 +1,109 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: module_init.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains the init/power/shutdown prototypes for all optional
+ *  (and possibly other) modules.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _MODULE_INIT_H
+#define _MODULE_INIT_H
+
+#include <config.h>
+#include <context.h>
+
+extern int mode_init(igd_context_t *context);
+extern int dsp_init(igd_context_t *context);
+extern int pi_init(igd_context_t *context);
+extern int _init_2d(igd_context_t *context);
+extern int _blend_init(igd_context_t *context);
+extern int _overlay_init(igd_context_t *context, igd_param_t *params);
+extern int _cmd_init(igd_context_t *context);
+extern int _pwr_init(igd_context_t *context);
+extern int _reset_init(igd_context_t *context);
+extern int _reg_init(igd_context_t *context, unsigned long flags);
+extern int appcontext_init(igd_context_t *context);
+extern int gmm_init(igd_context_t *context, unsigned long scratch_mem,
+		unsigned long max_fb_size);
+extern void gmm_shutdown(igd_context_t *context);
+
+
+#ifdef CONFIG_2D
+#define INIT_2D(c) _init_2d(c);
+#else
+#define INIT_2D(c) 0
+#endif
+
+#ifdef CONFIG_BLEND
+#define BLEND_INIT(c) _blend_init(c);
+#else
+#define BLEND_INIT(c) 0
+#endif
+
+#ifdef CONFIG_OVERLAY
+#define OVERLAY_INIT(c, p) _overlay_init(c, p)
+#else
+#define OVERLAY_INIT(a, p) 0
+#endif
+
+#ifdef CONFIG_CMD
+#define CMD_INIT(a) _cmd_init(a);
+#else
+#define CMD_INIT(a) 0
+#endif
+
+#ifdef CONFIG_POWER
+#define PWR_INIT(a) _pwr_init(a);
+#else
+#define PWR_INIT(a) 0
+#endif
+
+#ifdef CONFIG_REG
+#define REG_INIT(a, b) _reg_init(a, b);
+#else
+#define REG_INIT(a, b) 0
+#endif
+
+#ifdef CONFIG_RESET
+#define RESET_INIT(a) _reset_init(a);
+#else
+#define RESET_INIT(a) 0
+#endif
+
+#ifdef CONFIG_INTERRUPT
+#define INTERRUPT_INIT(did, mmadr) OS_INIT_INTERRUPT(did, mmadr);
+#else
+#define INTERRUPT_INIT(did, mmadr) 0
+#endif
+
+#ifdef CONFIG_APPCONTEXT
+#define APPCONTEXT_INIT(a) appcontext_init(a)
+#else
+#define APPCONTEXT_INIT(a) 0
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/msvdx.h b/drivers/gpu/drm/emgd/emgd/include/msvdx.h
new file mode 100644
index 0000000..19ec924
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/msvdx.h
@@ -0,0 +1,257 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: msvdx.h
+ * $Revision: 1.20 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF 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;
+};
+
+/* 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);
+int msvdx_create_context(igd_context_t *context);
+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);
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/pci.h b/drivers/gpu/drm/emgd/emgd/include/pci.h
new file mode 100644
index 0000000..9a5fc5c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/pci.h
@@ -0,0 +1,257 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pci.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains OS abstractions for PCI function calls.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OAL_PCI_H
+#define _OAL_PCI_H
+
+
+/*
+ * Standard PCI register definitions.
+ * Only the first 64 bytes are standardized so thiese must all be
+ * defined to numbers less than 0x40
+ */
+#define PCI_RID            0x08
+
+#define PCI_BAR_0           0x10
+#define PCI_BAR_1           0x14
+#define PCI_BAR_2           0x18
+#define PCI_BAR_3           0x1c
+#define PCI_BAR_4           0x20
+#define PCI_BAR_5           0x24
+
+#define PCI_INTERRUPT_LINE  0x3c
+
+/*
+ * This macro _may_ be defined by an OAL port to enable the PCI device
+ * Commonly this is used to enable the device on EFI
+ * The prototype of the function looks like this:
+ * int os_enable_pci(os_pci_dev dev);
+ * The return value from this function should be 0 to indicate success
+ * or non zero to indicate failure.
+ */
+#ifdef _OS_ENABLE_PCI
+#define OS_ENABLE_PCI(a) _OS_ENABLE_PCI(a)
+#else
+#define OS_ENABLE_PCI(a) 0
+#endif
+
+#define OS_PCI_GET_SLOT_ADDRESS(p, b, s, f) os_pci_get_slot_address(p, b, s, f)
+#define OS_PCI_READ_CONFIG_8(p, o, v)       os_pci_read_config_8(p, o, (v))
+#define OS_PCI_READ_CONFIG_16(p, o, v)      os_pci_read_config_16(p, o, (v))
+#define OS_PCI_READ_CONFIG_32(p, o, v)      os_pci_read_config_32(p, o, (v))
+#define OS_PCI_WRITE_CONFIG_8(p, o, v)      os_pci_write_config_8(p, o, v)
+#define OS_PCI_WRITE_CONFIG_16(p, o, v)     os_pci_write_config_16(p, o, v)
+#define OS_PCI_WRITE_CONFIG_32(p, o, v)     os_pci_write_config_32(p, o, v)
+#define OS_PCI_FREE_DEVICE(p)               os_pci_free_device(p)
+
+#define OS_PCI_FIND_DEVICE(v, d, p, bus, dev, func) \
+	os_pci_find_device(v, d, p, bus, dev, func)
+
+/*****************************************************************************
+ * Variable: os_pci_dev_t
+ *
+ * Description:
+ *  This is a data type that serves as a handle for allocated PCI device.
+ *
+ ****************************************************************************/
+typedef unsigned char *os_pci_dev_t;
+
+
+/*****************************************************************************
+ * Function: os_pci_find_device
+ *
+ * Parameters:
+ *  vendor_id : The vendor ID for the device to be found.
+ *  device_id : The vendor ID for the device to be found.
+ *  bus       : The bus number of the device in the PCI topology
+ *  dev       : The device number of the device in the PCI topology
+ *  func      : The function number of the device in the PCI topology
+ *  pci_device: The last found os_pci_dev_t or NULL.
+ *
+ * Description:
+ *  This function will find the PCI device for the paticular vendor and device,
+ *  bus, device, and function number.The pci_device parameter should be NULL when
+ *  calling the first time
+ *  and the last returned value when searching for multiple devices of
+ *  the same ID.
+ *
+ *  Notes: If the bus number is 0xFFFF, then the function searches for that
+ *  vendor_id, device_id pair in the whole PCI topology of the system i.e
+ *  it goes through all the buses, devices, functions in the system
+ *
+ ****************************************************************************/
+os_pci_dev_t os_pci_find_device(
+		unsigned short vendor_id,
+		unsigned short device_id,
+		unsigned short bus,
+		unsigned short dev,
+		unsigned short func,
+		os_pci_dev_t pci_dev);
+
+/*****************************************************************************
+ * Function: os_get_slot_address
+ *
+ * Parameters:
+ *  pci_device: The os_pci_dev_t to query.
+ *  bus: The returned bus or NULL if the bus is not needed.
+ *  slot: The returned slot or NULL if the bus is not needed.
+ *  func: The returned func or NULL if the bus is not needed.
+ *
+ * Description:
+ *  This function will return the bus slot and function for an os_pci_dev_t
+ *  previously obtained from os_pci_find_device(). Any of the bus/slot/func
+ *  parameters may be null if the information is not needed.
+ *
+ ****************************************************************************/
+int os_pci_get_slot_address(
+	os_pci_dev_t pci_dev,
+	unsigned int *bus,
+	unsigned int *slot,
+	unsigned int *func);
+
+/*****************************************************************************
+ * Function: os_pci_read_config_8
+ *
+ * Description:
+ *  This function retrieves a byte of information, starting at the specified
+ *  offset, from the PCI configuration space on a particular PCI device.
+ *
+ ****************************************************************************/
+int os_pci_read_config_8(
+		os_pci_dev_t pci_dev,
+		unsigned long offset,
+		unsigned char* val
+		);
+
+
+/*****************************************************************************
+ * Function: os_pci_read_config_16
+ *
+ * Description:
+ *  This function retrieves a word of information, starting at the specified
+ *  offset, from the PCI configuration space on a particular PCI device.
+ *
+ ****************************************************************************/
+int os_pci_read_config_16(
+		os_pci_dev_t pci_dev,
+		unsigned long offset,
+		unsigned short* val
+		);
+
+
+/*****************************************************************************
+ * Function: os_pci_read_config_32
+ *
+ * Description:
+ *  This function retrieves double word of information, starting at the
+ *  specified offset, from the PCI configuration space on a particular PCI
+ *  device.
+ *
+ ****************************************************************************/
+int os_pci_read_config_32(
+		os_pci_dev_t pci_dev,
+		unsigned long offset,
+		unsigned long* val
+		);
+
+
+/*****************************************************************************
+ * Function: os_pci_write_config_8
+ *
+ * Description:
+ *  This function sets a byte of data, starting at the specified offset, to
+ *  the PCI configuration space for a particular PCI device.
+ *
+ ****************************************************************************/
+int os_pci_write_config_8(
+		os_pci_dev_t pci_dev,
+		unsigned long offset,
+		unsigned char val
+		);
+
+
+/*****************************************************************************
+ * Function: os_pci_write_config_16
+ *
+ * Description:
+ *  This function sets a word of data, starting at the specified offset, to
+ *  the PCI configuration space for a particular PCI device.
+ *
+ ****************************************************************************/
+int os_pci_write_config_16(
+		os_pci_dev_t pci_dev,
+		unsigned long offset,
+		unsigned short val
+		);
+
+
+/*****************************************************************************
+ * Function: os_pci_write_config_32
+ *
+ * Description:
+ *  This function sets double word of data, starting at the specified offset,
+ *  to the PCI configuration space for a particular PCI device.
+ *
+ ****************************************************************************/
+int os_pci_write_config_32(
+		os_pci_dev_t pci_dev,
+		unsigned long offset,
+		unsigned long val
+		);
+
+
+/*****************************************************************************
+ * Function: os_pci_disable_legacy_vga_decoding
+ *
+ * Description:
+ *  Disabled legacy VGA decoding on a specific PCI device if the kernel is
+ *  compiled with support for the VGA arbiter.  If the VGA arbiter is not
+ *  compiled in, this function is a noop.
+ *
+ ****************************************************************************/
+int os_pci_disable_legacy_vga_decoding(
+		os_pci_dev_t pci_dev
+		);
+
+
+/*****************************************************************************
+ * Function: os_pci_free_device
+ *
+ * Description:
+ *  This function free the os_pci_dev_t * that previously allocated with the
+ *  os_pci_find_device.
+ *
+ ****************************************************************************/
+void os_pci_free_device(
+		os_pci_dev_t pci_dev
+		);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/pd.h b/drivers/gpu/drm/emgd/emgd/include/pd.h
new file mode 100644
index 0000000..388a2af
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/pd.h
@@ -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/drivers/gpu/drm/emgd/emgd/include/pd_init.h b/drivers/gpu/drm/emgd/emgd/include/pd_init.h
new file mode 100644
index 0000000..eb78285
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/pd_init.h
@@ -0,0 +1,191 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pd_init.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains configurable definitions to statically link port
+ *  drivers with display driver.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PD_INIT_H
+#define _PD_INIT_H
+
+#include <config.h>
+
+/* Enable Analog (CRT) port driver */
+#ifdef CONFIG_PD_ANALOG
+extern int analog_init(void *handle);
+#define ANALOG_INIT(handle)  analog_init(handle)
+#else
+#define ANALOG_INIT(handle)  0
+#endif
+
+/* Enable RGBA port driver */
+#ifdef CONFIG_PD_RGBA
+extern int rgba_init(void *handle);
+#define RGBA_INIT(handle)  rgba_init(handle)
+#else
+#define RGBA_INIT(handle)  0
+#endif
+
+/* Enable Silicon Image 154/164 FP port driver */
+#ifdef CONFIG_PD_SII164
+extern int sii164_init(void *handle);
+#define SII164_INIT(handle)  sii164_init(handle)
+#else
+#define SII164_INIT(handle)  0
+#endif
+
+/* Enable Texas Instruments 410 FP port driver */
+#ifdef CONFIG_PD_TI410
+extern int ti410_init(void *handle);
+#define TI410_INIT(handle)  ti410_init(handle)
+#else
+#define TI410_INIT(handle)  0
+#endif
+
+/* Enable Chrontel 7009 TMDS & TVOut port driver */
+#ifdef CONFIG_PD_CH7009
+extern int ch7009_init(void *handle);
+#define CH7009_INIT(handle)  ch7009_init(handle)
+#else
+#define CH7009_INIT(handle)  0
+#endif
+
+/* Enable National Semiconductor 2501 LVDS port driver */
+#ifdef CONFIG_PD_NS2501
+extern int ns2501_init(void *handle);
+#define NS2501_INIT(handle)  ns2501_init(handle)
+#else
+#define NS2501_INIT(handle)  0
+#endif
+
+/* Enable TL955 port driver */
+#ifdef CONFIG_PD_TL955
+extern int tl955_init(void *handle);
+#define TL955_INIT(handle)  tl955_init(handle)
+#else
+#define TL955_INIT(handle)  0
+#endif
+
+/* Enable Th164 port driver */
+#ifdef CONFIG_PD_TH164
+extern int th164_init(void *handle);
+#define TH164_INIT(handle)  th164_init(handle)
+#else
+#define TH164_INIT(handle)  0
+#endif
+
+/* Enable FS454 port driver */
+#ifdef CONFIG_PD_FS454
+extern int fs454_init(void *handle);
+#define FS454_INIT(handle)  fs454_init(handle)
+#else
+#define FS454_INIT(handle)  0
+#endif
+
+/* Enable NS387/389 port driver */
+#ifdef CONFIG_PD_NS387
+extern int ns387_init(void *handle);
+#define NS387_INIT(handle)  ns387_init(handle)
+#else
+#define NS387_INIT(handle)  0
+#endif
+
+/* Enable connexant port driver */
+#ifdef CONFIG_PD_CX873
+extern int cx873_init(void *handle);
+#define CX873_INIT(handle)  cx873_init(handle)
+#else
+#define CX873_INIT(handle)  0
+#endif
+
+/* Enable Internal LVDS port driver */
+#ifdef CONFIG_PD_LVDS
+extern int lvds_init(void *handle);
+#define LVDS_INIT(handle)  lvds_init(handle)
+#else
+#define LVDS_INIT(handle)  0
+#endif
+
+/* Enable SDVO port driver */
+#ifdef CONFIG_PD_SDVO
+extern int sdvo_init(void *handle);
+#define SDVO_INIT(handle)  sdvo_init(handle)
+#else
+#define SDVO_INIT(handle)  0
+#endif
+
+/* Enable Integrated TV port driver for NAPA*/
+#ifdef CONFIG_PD_TV
+extern int tv_init(void *handle);
+#define TV_INIT(handle)  tv_init(handle)
+#else
+#define TV_INIT(handle)  0
+#endif
+
+/* Enable FS460 port driver */
+#ifdef CONFIG_PD_FS460
+extern int fs460_init(void *handle);
+#define FS460_INIT(handle)  fs460_init(handle)
+#else
+#define FS460_INIT(handle)  0
+#endif
+
+/* Enable FS450 port driver */
+#ifdef CONFIG_PD_FS450
+extern int fs450_init(void *handle);
+#define FS450_INIT(handle)  fs450_init(handle)
+#else
+#define FS450_INIT(handle)  0
+#endif
+
+/* Enable Chrontel 7017 LVDS & TVOut port driver */
+#ifdef CONFIG_PD_CH7017
+extern int ch7017_init(void *handle);
+#define CH7017_INIT(handle)  ch7017_init(handle)
+#else
+#define CH7017_INIT(handle)  0
+#endif
+
+/* Enable internal HDMI port driver */
+#ifdef CONFIG_PD_HDMI
+extern int hdmi_init(void *handle);
+#define HDMI_INIT(handle)  hdmi_init(handle)
+#else
+#define HDMI_INIT(handle)  0
+#endif
+
+/* Enable Dummy Port Driver*/
+#ifdef CONFIG_PD_PD000
+extern int pd000_init(void *handle);
+#define PD000_INIT(handle)  pd000_init(handle)
+#else
+#define PD000_INIT(handle)  0
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/pi.h b/drivers/gpu/drm/emgd/emgd/include/pi.h
new file mode 100644
index 0000000..d14d39e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/pi.h
@@ -0,0 +1,86 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pi.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PI_H_
+#define _PI_H_
+
+#include <context.h>
+#include <mode.h>
+#include <pd.h>
+
+/* power states */
+#define IGD_DEVICE_ON 1
+#define IGD_DEVICE_OFF 0
+
+#define PI_FIRMWARE_EDID          0x1
+#define PI_FIRMWARE_DISPLAYID     0x2
+
+/* get_native_dtd() flags */
+#define PI_ALL_TIMINGS            0x0001
+#define PI_SUPPORTED_TIMINGS      0x0002
+extern unsigned long get_native_dtd(igd_timing_info_t *timing_table,
+	unsigned long flags, pd_timing_t **native_dtd, unsigned long native_flags);
+
+extern igd_timing_info_t crt_timing_table[];
+extern int crt_timing_table_size;
+
+#ifndef CONFIG_MICRO
+extern igd_timing_info_t cea_timing_table[];
+extern int cea_timing_table_size;
+extern type_std_t cea_std_lookup[];
+extern int cea_std_lookup_size;
+#endif
+
+extern int pi_pd_register(pd_driver_t *pd_driver);
+extern int pi_pd_register(pd_driver_t *pd_driver);
+extern int pi_read_regs(void *callback_context, pd_reg_t *list,
+		unsigned long reg_type);
+extern int pi_write_regs(void *callback_context, pd_reg_t *list,
+		unsigned long reg_type);
+extern int pi_program_port_dvo(igd_display_context_t *, unsigned long);
+extern int pi_program_port_analog(igd_display_context_t *, unsigned long);
+extern int pi_program_port_rgba(igd_display_context_t *, unsigned long);
+extern int pi_program_port_lvds(igd_display_context_t *, unsigned long);
+
+/* Function to get attr value from port driver attr list */
+extern int pi_pd_find_attr_and_value(igd_display_port_t *port,
+						  unsigned long attr_id,
+						  unsigned long flag,
+						  pd_attr_t   **caller_pd_attr,
+						  unsigned long * attr_value);
+
+/* Function to get attr value from user provided init attribute list */
+extern int pi_get_port_init_attr(igd_display_port_t *port,
+		unsigned long id,
+		unsigned long *value);
+extern int pi_save_mode_state(igd_display_port_t *port,
+		reg_state_id_t reg_state_id);
+#endif /* _PI_H_ */
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/appcontext.h b/drivers/gpu/drm/emgd/emgd/include/plb/appcontext.h
new file mode 100644
index 0000000..3a1417c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/appcontext.h
@@ -0,0 +1,67 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: appcontext.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the inter-module header file for the client context module.
+ *  It contains data structures needed for modules to use and manipulate
+ *  the device state including hardware context switching.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _APPCONTEXT_PLB_H
+#define _APPCONTEXT_PLB_H
+
+#include <context.h>
+#include <igd_mode.h>
+
+/*
+ * This data structure contains a copy of all needed state variables and
+ * the logical context used by hardware for context switching. An IGD
+ * client driver can allocate a client context for each client or allocate
+ * just one to be shared by all clients.
+ */
+/*
+ * TODO:
+ * Add or modify the struct and other definitions for Poulsbo
+ */
+typedef struct _appcontext {
+	void *state3d;
+	void *state2d;
+	unsigned char *hw_context_virt;
+	unsigned long hw_context_phys;
+	unsigned long hw_context_offset;
+}appcontext_t, appcontext_plb_t;
+
+int appcontext_set_plb(igd_display_h display,
+	int priority,
+	appcontext_t *context,
+	int extstate_save_enable,
+	int extstate_restore_enable,
+	int force_restore,
+	int restore_inhibit);
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/cmd.h b/drivers/gpu/drm/emgd/emgd/include/plb/cmd.h
new file mode 100644
index 0000000..c4252cb
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/cmd.h
@@ -0,0 +1,43 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: cmd.h
+ * $Revision: 1.13 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Device dependent header file for the command interface for poulsbo
+ *  devices.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PLB_CMD_H
+#define _PLB_CMD_H
+
+#include <io.h>
+#include <sched.h>
+
+#include <instr_common.h>
+#include <utils.h>
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/context.h b/drivers/gpu/drm/emgd/emgd/include/plb/context.h
new file mode 100644
index 0000000..563c232
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/context.h
@@ -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/drivers/gpu/drm/emgd/emgd/include/plb/instr.h b/drivers/gpu/drm/emgd/emgd/include/plb/instr.h
new file mode 100644
index 0000000..791808a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/instr.h
@@ -0,0 +1,224 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: instr.h
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+/*
+ * TODO:
+ * Add or modify the struct and other definitions for Poulsbo
+ */
+#ifndef _INSTR_PLB_H
+#define _INSTR_PLB_H
+
+#include <instr_common.h>
+
+typedef struct _igd_vertex {
+	unsigned long x;
+	unsigned long x_ieee_fp;
+	unsigned long y;
+	unsigned long y_ieee_fp;
+	unsigned long z;
+	unsigned long z_ieee_fp;
+	unsigned long argb;
+} igd_vertex_t, *pigd_vertex_t;
+
+/* Common FP numbers */
+#define IEEE_FP_0 0x00000000
+#define IEEE_FP_1 0x3f800000
+
+/* For EMGD_WRITE32 */
+#include <io.h>
+
+
+/* All instruction sizes must be Double DWORD aligned for the current
+ * platform.  The exception to this is the NOOP, which may be useful
+ * not being Double DWORD aligned. */
+
+/* color depth */
+#define PLB_PF_1BIT_PALETTE      0x0
+#define PLB_PF_2BIT_PALETTE      0x1
+#define PLB_PF_4BIT_PALETTE      0x2
+#define PLB_PF_8BIT_PALETTE      0x3
+#define PLB_PF_8BIT_ALPHA        0x4
+#define PLB_PF_4BIT_ALPHA        0x5
+#define PLB_PF_8BPP              0x6
+#define PLB_PF_16BPP4444         0x7
+#define PLB_PF_16BPP555          0x8
+#define PLB_PF_16BPP1555         0x9
+#define PLB_PF_16BPP565          0xA
+#define PLB_PF_24BPP             0xB
+#define PLB_PF_32BPP             0xC
+#define PLB_PF_32BPP_UYVY        0xD
+#define PLB_PF_32BPP_AYUV        0xE
+
+/*-----------------*/
+/* 2D Instructions */
+/*-----------------*/
+/* Size of 2D Instructions */
+#define PLB_2D_PAT_CONTROL_SIZE    1
+#define PLB_2D_CONTROL_SIZE        3
+#define PLB_2D_SRC_SURF_SIZE       2
+#define PLB_2D_DEST_SURF_SIZE      2
+#define PLB_2D_PAT_SURF_SIZE       2
+#define PLB_2D_MASK_SURF_SIZE      2
+#define PLB_2D_SRC_OFFSET_SIZE     1
+#define PLB_2D_MASK_OFFSET_SIZE    1
+#define PLB_2D_SRC_PAL_SIZE        1
+#define PLB_2D_PAT_PAL_SIZE        1
+/* The 2D_BLT_SIZE is different when doing a Fill */
+#define PLB_2D_BLT_SIZE            3
+#define PLB_2D_BLT_FILL_SIZE       4
+#define PLB_2D_CLIP_SIZE           2
+#define PLB_2D_FENCE_SIZE          1
+#define PLB_2D_FLUSH_SIZE          1
+#define PLB_2D_BLT_SRC_COPY_SIZE   3
+
+/* 2D instruction (BR0) */
+#define _PLB_2D_CLIP        (0x0 << 28)
+#define _PLB_2D_PAT_CONTROL (0x1 << 28)
+#define _PLB_2D_CONTROL     (0x2 << 28)
+#define _PLB_2D_SRC_OFFSET  (0x3 << 28)
+#define _PLB_2D_MASK_OFFSET (0x4 << 28)
+#define _PLB_2D_FENCE       (0x7 << 28)
+#define _PLB_2D_BLT         (0x8 << 28)
+#define _PLB_2D_SRC_SURF    (0x9 << 28)
+#define _PLB_2D_DEST_SURF   (0xa << 28)
+#define _PLB_2D_PAT_SURF    (0xb << 28)
+#define _PLB_2D_SRC_PAL     (0xc << 28)
+#define _PLB_2D_PAT_PAL     (0xd << 28)
+#define _PLB_2D_MASK_SURF   (0xe << 28)
+#define _PLB_2D_FLUSH       (0xf << 28)
+
+/* In 2D Control */
+#define PSB_2D_SRCCK_CTRL     1
+#define PSB_2D_DSTCK_CTRL     2
+#define PSB_2D_ALPHA_CTRL     4
+
+#define PLB_2D_BLT_CTRL_ROT_0      0
+#define PLB_2D_BLT_CTRL_ROT_90     (1<<25)
+#define PLB_2D_BLT_CTRL_ROT_180    (2<<25)
+#define PLB_2D_BLT_CTRL_ROT_270    (3<<25)
+
+/* Top Left or Bottom Right */
+#define PLB_2D_BLT_CTRL_ORDER_TL2BR   0
+#define PLB_2D_BLT_CTRL_ORDER_BR2TL   (1<<23)
+#define PLB_2D_BLT_CTRL_ORDER_TR2BL   (2<<23)
+#define PLB_2D_BLT_CTRL_ORDER_BL2TR   (3<<23)
+
+#define PLB_2D_BLT_CTRL_DEST_CK_DISABLE     0
+#define PLB_2D_BLT_CTRL_DEST_CK_PASS_MATCH  (1<<21)
+#define PLB_2D_BLT_CTRL_DEST_CK_KILL_MATCH  (2<<21)
+
+#define PLB_2D_BLT_CTRL_SRC_CK_DISABLE     0
+#define PLB_2D_BLT_CTRL_SRC_CK_PASS_MATCH  (1<<19)
+#define PLB_2D_BLT_CTRL_SRC_CK_KILL_MATCH  (2<<19)
+
+#define PLB_2D_BLT_CTRL_CLIP_DISABLE  0
+#define PLB_2D_BLT_CTRL_CLIP_ENABLE   (1<<18)
+
+#define PLB_2D_BLT_CTRL_ALPHA_BLEND_DISABLE  0
+#define PLB_2D_BLT_CTRL_ALPHA_BLEND_ENABLE   (1<<17)
+
+#define PLB_2D_BLT_CTRL_FILL      0
+#define PLB_2D_BLT_CTRL_PATTERN   (1<<16)
+
+/*----------------*/
+/* 2D Abstraction */
+/*----------------*/
+#define PLB_2D_CLIP(queue, xmin, xmax, ymin, ymax)               \
+    CMD_2D_WRITE_PLB(queue, _PLB_2D_CLIP | (xmax << 12) | xmin); \
+    CMD_2D_WRITE_PLB(queue, (ymax << 12) | ymin);
+
+#define PLB_2D_PAT_CONTROL(queue, pt, width, height)                       \
+	CMD_2D_WRITE_PLB(queue, _PLB_2D_PAT_CONTROL | (pt.x << 15) |           \
+                     (pt.y << 10) | (width << 5) | height);
+
+#define PLB_2D_CONTROL(queue, ctrl_flag, ck_color, ck_mask)                \
+	CMD_2D_WRITE_PLB(queue, _PLB_2D_CONTROL | ctrl_flag);                  \
+	CMD_2D_WRITE_PLB(queue, ck_color);                                     \
+	CMD_2D_WRITE_PLB(queue, ck_mask);
+
+#define PLB_2D_FENCE(queue)                                                \
+	CMD_2D_WRITE_PLB(queue, _PLB_2D_FENCE);
+
+#define PLB_2D_FLUSH(queue)                                                \
+	CMD_2D_WRITE_PLB(queue, _PLB_2D_FLUSH);
+
+#define PLB_2D_DEST_SURF(queue, pf, pitch, offset)                         \
+	CMD_2D_WRITE_PLB(queue, _PLB_2D_DEST_SURF | (pf<<15) | pitch);         \
+	CMD_2D_WRITE_PLB(queue, offset);
+
+#define PLB_2D_SRC_SURF(queue, pf, pitch, offset)                          \
+	CMD_2D_WRITE_PLB(queue, _PLB_2D_SRC_SURF | (pf<<15) | pitch);          \
+	CMD_2D_WRITE_PLB(queue, offset);
+
+#define PLB_2D_PAT_SURF(queue, pf, pitch, offset)                          \
+	CMD_2D_WRITE_PLB(queue, _PLB_2D_PAT_SURF | (pf<<15) | pitch);          \
+	CMD_2D_WRITE_PLB(queue, offset);
+
+#define PLB_2D_MASK_SURF(queue, pitch, offset)                             \
+	CMD_2D_WRITE_PLB(queue, _PLB_2D_MASK_SURF | pitch);                    \
+	CMD_2D_WRITE_PLB(queue, offset);
+
+#define PLB_2D_SRC_OFFSET(queue, pt)                                       \
+	CMD_2D_WRITE_PLB(queue, _PLB_2D_SRC_OFFSET | (pt.x<<12) | pt.y);
+
+#define PLB_2D_MASK_OFFSET(queue, pt)                                      \
+	CMD_2D_WRITE_PLB(queue, _PLB_2D_MASK_OFFSET | (pt.x<<12) | pt.y);
+
+#define PLB_2D_SRC_PAL(queue, offset)                                      \
+	CMD_2D_WRITE_PLB(queue, _PLB_2D_SRC_PAL | offset);
+
+#define PLB_2D_PAT_PAL(queue, offset)                                      \
+	CMD_2D_WRITE_PLB(queue, _PLB_2D_PAT_PAL | offset);
+
+/* Color fill from Top Left to Bottom Right */
+#define PLB_2D_BLT_FILL_TL2BR(queue, control, rop, fill, rect)             \
+	CMD_2D_WRITE_PLB(queue, _PLB_2D_BLT | control | (rop<<8) | rop);       \
+	CMD_2D_WRITE_PLB(queue, fill);                                         \
+	CMD_2D_WRITE_PLB(queue, (rect->x1<<12) | rect->y1);                    \
+	CMD_2D_WRITE_PLB(queue, ((rect->x2-rect->x1)<<12) |                    \
+                     (rect->y2-rect->y1));
+
+/* Color fill from Bottom Right to Top Left */
+#define PLB_2D_BLT_FILL_BR2TL(queue, control, rop, fill, rect)             \
+	CMD_2D_WRITE_PLB(queue, _PLB_2D_BLT | control | (rop<<8) | rop);       \
+	CMD_2D_WRITE_PLB(queue, fill);                                         \
+	CMD_2D_WRITE_PLB(queue, ((rect->x2-1)<<12) | (rect->y2-1));            \
+	CMD_2D_WRITE_PLB(queue, ((rect->x2-rect->x1)<<12) |                    \
+                     (rect->y2-rect->y1));
+
+#define PLB_2D_BLT_SRC_COPY(queue, control, rop, pt, w, h)                 \
+	CMD_2D_WRITE_PLB(queue, _PLB_2D_BLT | control | (rop<<8) | rop);       \
+	CMD_2D_WRITE_PLB(queue, (pt.x<<12) | pt.y);                            \
+	CMD_2D_WRITE_PLB(queue, (w<<12) | h);
+
+#define PLB_2D_BLT_CHROMA(queue, chroma_color)                             \
+	CMD_2D_WRITE_PLB(queue, chroma_color);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/mi.h b/drivers/gpu/drm/emgd/emgd/include/plb/mi.h
new file mode 100644
index 0000000..fcbc706
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/mi.h
@@ -0,0 +1,77 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mi.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is a header file for the Intel GFX commands.
+ *  This includes commands specific to Intel hardware and structures specific
+ *  to Intel hardware.  All other commands and structures are available
+ *  through GFX.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _MI_H
+#define _MI_H
+
+#include <igd_mode.h>
+#include <igd_render.h>
+
+/* FIXME: This file has not been checked for PLB. */
+
+#define MI_FLUSH_OPTIONS_MASK 0x0000000f
+#define MI_FLUSH_MAP          0x00000001
+#define MI_FLUSH_RENDER       0x00000004
+/* #define MI_FLUSH_END_SCENE    0x00000008  Not available on PLB? */
+/* #define MI_FLUSH_WRITE_DIRTY  0x00000010  Not available on PLB? */
+
+extern int mi_display_buffer_info_plb(igd_display_h display_h,
+	int priority,
+	unsigned long flags);
+
+extern int mi_wait_scan_priority_arb_on_off_plb(igd_command_t *addr,
+	int priority, int enable);
+
+extern int mi_wait_scan_lines_excl_plb(igd_display_h display_h,
+	int priority,
+	unsigned long start,
+	unsigned long end);
+
+extern int mi_wait_scan_lines_incl_plb(igd_display_h display_h,
+	int priority,
+	unsigned long start,
+	unsigned long end);
+
+extern int mi_wait_vblank_plb(igd_display_h display_h,
+	int priority);
+
+extern int mi_flush_plb(igd_display_h display_h, int priority,
+	unsigned int flush_options, unsigned int flags);
+
+extern int mi_wait_for_scan_plb(igd_display_h display_h, int priority,
+	igd_rect_t *dest_rect);
+
+extern int mi_user_interrupt_plb(igd_display_h display_h, int priority);
+
+#endif /* _MI_H */
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/regs.h b/drivers/gpu/drm/emgd/emgd/include/plb/regs.h
new file mode 100644
index 0000000..95d880f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/regs.h
@@ -0,0 +1,747 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: regs.h
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the register definition file for the PLB platform. This should
+ *  contain device dependent register definitions. Standard register
+ *  definitions (VGA, PCI, etc) should not be put in this file. For those
+ *  see pci.h or vga.h.
+ *-----------------------------------------------------------------------------
+ */
+
+/*
+ * Note: Use _REGS_H_  instead of _PLB_REGS_H_ to insure that no file can
+ * include 2 device dependent register files.
+ */
+#ifndef _REGS_H_
+#define _REGS_H_
+
+#include <pci.h>
+#include <psb_regs.h>
+#include <msvdx.h>
+
+/*-----------------------------------------------------------------------------
+ * PCI Register Definitions
+ *---------------------------------------------------------------------------*/
+#define PLB_PCI_MMADR      PCI_BAR_0
+#define PLB_PCI_IOBAR      PCI_BAR_1
+#define PLB_PCI_GMADR      PCI_BAR_2
+#define PLB_PCI_GTTADR     PCI_BAR_3
+
+#define PLB_PCI_GC         0x52
+#define PLB_PCI_BSM        0x5C
+
+#define PLB_MMIO_SIZE  (512*1024)
+#define PLB_GTT_SIZE   (128*1024)
+
+
+/*-----------------------------------------------------------------------------
+ * Display Plane A Register Definitions (70180h - 70188h)
+ *---------------------------------------------------------------------------*/
+#define DSPAAFLIP    0x7017C
+#define DSPACNTR     0x70180
+#define DSPAADDR     0x70184
+#define DSPASTRIDE   0x70188
+#define DSPASIZE     0x70190
+#define DSPAKEYVAL   0x70194
+#define DSPAKEYMASK  0x70198
+
+/*
+ * FIXME: Review and clean up this file. Everything below this point needs
+ * to be reviewed for accuracy or removed.
+ */
+
+
+
+/*-----------------------------------------------------------------------------
+ * General VGA Register Definitions
+ *---------------------------------------------------------------------------*/
+#define FEATURE_CONT_REG      0x3DA  /* Feature Control Register */
+#define FEATURE_CONT_REG_MONO 0x3BA  /* Feature Control Register (Mono) */
+#define FEATURE_CONT_REG_READ 0x3CA  /* Feature Control Register (Read) */
+#define MSR_PORT              0x3C2  /* Miscellaneous Output Port */
+#define MSR_PORT_LSB          0xC2   /* Miscellaneous Output Port LSB */
+#define MSR_READ_PORT         0x3CC  /* Miscellaneous Output Reg (Read) */
+#define STATUS_REG_00         0x3C2  /* Input Status Register 0 */
+#define STATUS_REG_01         0x3DA  /* Input Status Register 1 */
+#define STATUS_REG_01_MONO    0x3BA  /* Input Status Register 1 (Mono) */
+
+/* DAC Register Definitions. */
+#define DAC_PEL_MASK          0x3C6  /* Color Palette Pixel Mask Register */
+#define DAC_READ_INDEX        0x3C7  /* Color Palette Read-Mode Index Reg */
+#define DAC_STATE             0x3C7  /* Color Palette State Register */
+#define DAC_WRITE_INDEX       0x3C8  /* Color Palette Index Register */
+#define DAC_DATA_REG          0x3C9  /* Color Palette Data Register */
+
+
+/*-----------------------------------------------------------------------------
+ * Attribute Controller Register Definitions
+ *---------------------------------------------------------------------------*/
+#define AR_PORT_LSB  0xC0  /*Attribute Controller Index Port LSB */
+
+#define AR00  0x00  /* Color Data Register */
+#define AR01  0x01	/* Color Data Register */
+#define AR02  0x02	/* Color Data Register */
+#define AR03  0x03	/* Color Data Register */
+#define AR04  0x04	/* Color Data Register */
+#define AR05  0x05	/* Color Data Register */
+#define AR06  0x06	/* Color Data Register */
+#define AR07  0x07	/* Color Data Register */
+#define AR08  0x08	/* Color Data Register */
+#define AR09  0x09	/* Color Data Register */
+#define AR0A  0x0A	/* Color Data Register */
+#define AR0B  0x0B	/* Color Data Register */
+#define AR0C  0x0C	/* Color Data Register */
+#define AR0D  0x0D	/* Color Data Register */
+#define AR0E  0x0E	/* Color Data Register */
+#define AR0F  0x0F	/* Color Data Register */
+#define AR10  0x10	/* Mode Control Register */
+#define AR11  0x11	/* Overscan Color Register */
+#define AR12  0x12	/* Color Plane Enable Register */
+#define AR13  0x13	/* Horizontal Pixel Panning Register */
+#define AR14  0x14	/* Pixel Pad Register */
+
+
+/*-----------------------------------------------------------------------------
+ * CRT Controller Register Definitions
+ *---------------------------------------------------------------------------*/
+#define CR_PORT_LSB     0xD4  /* CRT Controller Index Port LSB */
+#define CRT_3D4	        0x3D4 /* Color CRTC Index Port */
+#define CRT_3B4	        0x3B4 /* Monochrome CRTC Index Port */
+
+#define CR00            0x00  /* Horizontal Total Register */
+#define CR01            0x01  /* Horizontal Display Enable End Reg */
+#define CR02            0x02  /* Horizontal Blank Start Register */
+#define CR03            0x03  /* Horizontal Blank End Register */
+#define CR04            0x04  /* Horizontal Sync Start Register */
+#define CR05            0x05  /* Horizontal Sync End Register */
+#define CR06            0x06  /* Vertical Total Register */
+#define CR07            0x07  /* Overflow Register */
+#define CR08            0x08  /* Preset Row Scan Register */
+#define CR09            0x09  /* Maximum Scan Line Register */
+#define DOUBLE_SCANLINE	BIT7  /* Double scan ( 1 = Enable ) */
+#define LCOMP_BIT9      BIT6  /* Bit 9 of line compare register */
+#define VBLANK_BIT9     BIT5  /* Bit 9 of vertical blank start */
+#define CR0A            0x0A  /* Cursor Start Scan Line Register */
+#define CR0B            0x0B  /* Cursor End Scan Line Register */
+#define CR0C            0x0C  /* Start Address High Register */
+#define CR0D            0x0D  /* Start Address Low Register */
+#define CR0E            0x0E  /* Cursor Location High Register */
+#define CR0F            0x0F  /* Cursor Location Low Register */
+#define CR10            0x10  /* Vertical Sync Start Register */
+#define CR11            0x11  /* Vertical Sync End Register */
+#define CR12            0x12  /* Vertical Display Enable End Reg */
+#define CR13            0x13  /* Offset Register */
+#define CR14            0x14  /* Underline Row Register */
+#define CR15            0x15  /* Vertical Blank Start Register */
+#define CR16            0x16  /* Vertical Blank End Register */
+#define CR17            0x17  /* CRT Mode Control Register */
+#define CR18            0x18  /* Line Compare Register */
+#define CR22            0x22  /* Memory Data Latches Register */
+#define CR24            0x24  /* Attribute Controller Toggle Reg */
+
+
+/*-----------------------------------------------------------------------------
+ * Graphics Controller Register Definitions
+ *---------------------------------------------------------------------------*/
+#define GR_PORT_LSB    0xCE   /* Graphics Controller Index Port LSB */
+
+#define GR00           0x00   /* Set/Reset Register */
+#define GR01           0x01   /* Enable Set/Reset Register */
+#define GR02           0x02   /* Color Compare Register */
+#define GR03           0x03   /* Data Rotate Register */
+#define GR04           0x04   /* Read Map Select Register */
+#define GR05           0x05   /* Graphics Mode Register */
+#define GR06           0x06   /* Micsellaneous Register */
+#define RANGE_MAP_MASK BIT3 + BIT2  /* Address range to map mask */
+#define A0_BF_RANGE    000h   /* Map to A0000h-BFFFFh range */
+#define GRAF_MODE      BIT0   /* 1 = Grahics mode, 0 = Text mode */
+#define GR07           0x07   /* Color Don't Care Register */
+#define GR08           0x08   /* Bit Mask Register */
+#define GR10           0x10   /* Address Mapping */
+#define PAGING_TARGET  BIT2 + BIT1 /* 00 = Local/Stolen, 01 = Memory mapped regs */
+#define PAGE_MODE      BIT0   /* Page Map allow access to all FB mem */
+#define GR11           0x11   /* Page Selector */
+#define	GR18           0x18   /* Software Flag */
+
+
+/*-----------------------------------------------------------------------------
+ * Sequencer Register Definitions
+ *---------------------------------------------------------------------------*/
+#define SR_PORT_DATA      0x3C5 /* Sequencer Data Port */
+#define SR_PORT_LSB       0xC4  /* Sequencer Index Port LSB */
+
+#define SR00              0x00  /* Reset Register */
+#define SR01              0x01  /* Clocking Mode Register */
+#define DOT_CLOCK_DIVIDE  BIT3	/* Divide pixel clock by 2 */
+#define SR02              0x02  /* Plane/Map Mask Register */
+#define SR03              0x03  /* Character Font Register */
+#define SR04              0x04  /* Memory Mode Register */
+#define SR07              0x07  /* Horizontal Character Counter Reset */
+
+
+
+
+
+#define PLB_OFFSET_VGA_MSAC         0x62
+#define INTEL_OFFSET_VGA_CORECLK    0xF0
+
+#define INTEL_OFFSET_BRIDGE_CAPREG  0xE0
+
+#define PCI_CAPREG_4      0x44 /* Capability Identification Reg[39:31] */
+#define PCI_MOBILE_BIT    BIT0
+
+#define PCI_GMS_MASK      BIT6 + BIT5 + BIT4 /* GFX Mode Select Bits Mask */
+#define PCI_LOCAL		  BIT4 /* Local memory enabled */
+#define PCI_DVMT_512K     BIT5 /* 512KB DVMT */
+#define PCI_DVMT_1M       BIT5 + BIT4 /* 1MB DVMT */
+#define PCI_DVMT_8M       BIT6 /* 8MB DVMT */
+
+#define PCI_DRB_REG       0x60 /* DRAM row boundary Register */
+#define PCI_DRC_REG       0x7C /* DRAM Controller Mode Register */
+#define PCI_DT_MASK       BIT0 + BIT1  /* Select SDRAM types.
+                                        *  = 00:  Single data rate SDRAM
+                                        *  = 01:  Dual data rate SDRAM
+                                        *  = Other:  Reserved
+                                        */
+#define DT_SDR_SDRAM      00   /* Single data rate SDRAM */
+#define DT_DDR_SDRAM      01   /* Dual data rate SDRAM */
+
+#define PCI_ESMRAMC_REG   0x91 /* Extended System Management RAM Reg */
+#define PCI_TSEG_SZ		  BIT1 /* TSEG size bit */
+#define PCI_TSEG_512K	  0    /* 512K TSEG */
+#define PCI_TSEG_1M       BIT1 /* 1MB TSEG */
+
+#define PCI_GCLKIO_REG    0xC0 /* GMCH Clock and IO Control Register */
+#define PCI_AGP_Bit       BIT9 /* AGP/DVO Mux Select:
+								*  = 0, DVO/ZV
+								*  = 1, AGP
+								*/
+#define PCI_GMCHCFG_REG   0xC6 /* GMCH Configuration Register */
+#define PCI_SMFREQ_MASK   BIT10 + BIT11
+						   /* System Mem Frequency Select
+                            * = 00:  Intel Reserved
+                            * = 01:  System Memory Frequency is 166Mhz (DDR333) - Intel Reserved
+                            * = 10:  System Memory Frequency is 133Mhz (SDR133, DDR266)
+                            * = 11:  System Memory Frequency is 100Mhz (DDR200)
+                            */
+#define SYS_MEM_FREQ_166  1  /* System Memory Frequency is 166Mhz */
+#define SYS_MEM_FREQ_133  2  /* System Memory Frequency is 133Mhz */
+#define SYS_MEM_FREQ_100  3  /* System Memory Frequency is 100Mhz */
+#define PCI_SMFREQ_POS    10 /* System Memory Frequency position  */
+
+#define PCI_CONFIG_LMINT  0xE0
+#define PREALLOCATED_SIZE (8 * 1024 * 1024)
+
+
+/*-----------------------------------------------------------------------------
+ * General VGA Register Definitions
+ *---------------------------------------------------------------------------*/
+#define FEATURE_CONT_REG      0x3DA  /* Feature Control Register */
+#define FEATURE_CONT_REG_MONO 0x3BA  /* Feature Control Register (Mono) */
+#define FEATURE_CONT_REG_READ 0x3CA  /* Feature Control Register (Read) */
+#define MSR_PORT              0x3C2  /* Miscellaneous Output Port */
+#define MSR_PORT_LSB          0xC2   /* Miscellaneous Output Port LSB */
+#define MSR_READ_PORT         0x3CC  /* Miscellaneous Output Reg (Read) */
+#define STATUS_REG_00         0x3C2  /* Input Status Register 0 */
+#define STATUS_REG_01         0x3DA  /* Input Status Register 1 */
+#define STATUS_REG_01_MONO    0x3BA  /* Input Status Register 1 (Mono) */
+
+/* DAC Register Definitions. */
+#define DAC_PEL_MASK          0x3C6  /* Color Palette Pixel Mask Register */
+#define DAC_READ_INDEX        0x3C7  /* Color Palette Read-Mode Index Reg */
+#define DAC_STATE             0x3C7  /* Color Palette State Register */
+#define DAC_WRITE_INDEX       0x3C8  /* Color Palette Index Register */
+#define DAC_DATA_REG          0x3C9  /* Color Palette Data Register */
+
+
+/*-----------------------------------------------------------------------------
+ * Memory mapped I/O Registers Definitions
+ *---------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------
+ * Instruction and Interrupt Control Registers (01000h - 02FFFh)
+ *---------------------------------------------------------------------------*/
+#define PGTBL_CTL         0x02020  /* Page Table Control Register */
+#define HWS_PGA           0x02080  /* Hardware Status Page Address register */
+#define HWSTAM            0x02098  /* Hardware Status Mask */
+#define SCPD0             0x0209C  /* Scratch Pad 0 (Debug) */
+#define IER               0x020A0  /* Interrupt Enable */
+#define IIR               0x020A4  /* Interrupt Identity */
+#define IMR               0x020A8  /* Interrupt Mask */
+#define ISR               0x020AC  /* Interrupt Status */
+#define EIR               0x020B0  /* Error Identity */
+#define EMR               0x020B4  /* Error Mask */
+#define ESR               0x020B8  /* Error Status */
+#define FW_BLC1           0x020D8  /* FIFO Watermark Burst Length Control */
+#define FW_BLC2           0x020DC  /* FIFO Watermark Burst Length Control */
+#define FW_BLC_SELF       0x020E0  /* Display FIFO Watermark */
+#define MI_ARB_STATE      0x020E4  /* Memory Interface Arbitration State */
+#define FW_BLC3           0x020EC  /* FIFO Watermark Burst Length Control */
+#define G_DEBUG           0x020FC  /* G-UNIT Debug enable register */
+
+
+/*-----------------------------------------------------------------------------
+ * FENCE and Per Process GTT Control Registers (02000h - 031FFh)
+ * --------------------------------------------------------------------------*/
+#define FENCE0            0x02000 /* Fence table registers */
+#define FENCE1            0x02004
+#define FENCE2            0x02008
+#define FENCE3            0x0200C
+#define FENCE4            0x02010
+#define FENCE5            0x02014
+#define FENCE6            0x02018
+#define FENCE7            0x0201C
+#define FENCE8            0x03000
+#define FENCE9            0x03004
+#define FENCE10           0x03008
+#define FENCE11           0x0300C
+#define FENCE12           0x03010
+#define FENCE13           0x03014
+#define FENCE14           0x03018
+#define FENCE15           0x0301C
+
+/*-----------------------------------------------------------------------------
+ * MISC I/0 Contol Register ( 05000h - 05FFFh )
+ *---------------------------------------------------------------------------*/
+#define IO_OFF          0x05000         /* Register group offset */
+
+#define IO00            0x05000         /* Hsync / Vsync control register */
+#define GPIO0           0x05010         /* GPIO register 0 (DDC1) */
+#define	DDC1_SCL_PIN    GPIO0_SCL_PIN   /* DDC1 SCL GPIO pin # */
+#define	DDC1_SDA_PIN    GPIO0_SDA_PIN   /* DDC1 SDA CPIO pin # */
+#define GPIO1           0x05014         /* GPIO register 1 (I2C) */
+#define	I2C_SCL_PIN     GPIO1_SCL_PIN   /* I2C SCL GPIO pin # */
+#define	I2C_SDA_PIN     GPIO1_SDA_PIN   /* I2C SDA CPIO pin # */
+#define GPIO2           0x05018         /* GPIO register 2 (DDC2) */
+#define	DDC2_SCL_PIN    GPIO2_SCL_PIN   /* DDC2 SCL GPIO pin # */
+#define	DDC2_SDA_PIN    GPIO2_SDA_PIN   /* DDC2 SDA CPIO pin # */
+#define GPIO3           0x0501C         /* GPIO register 3 (AGP mux DVI DDC) */
+#define GPIO4           0x05020         /* GPIO register 4 (AGP mux I2C) */
+#define GPIO5           0x05024         /* GPIO register 5 (AGP mux DDC2/I2C) */
+
+#define GPIOPIN0        GPIO0
+#define GPIOPIN1        GPIO0+1
+#define GPIOPIN2        GPIO1
+#define GPIOPIN3        GPIO1+1
+#define GPIOPIN4        GPIO2
+#define GPIOPIN5        GPIO2+1
+#define GPIOPIN6        GPIO3
+#define GPIOPIN7        GPIO3+1
+#define GPIOPIN8        GPIO4
+#define GPIOPIN9        GPIO4+1
+#define GPIOPIN10       GPIO5
+#define GPIOPIN11       GPIO5+1
+#define GPIOPINMAX      12
+
+#define GMBUS0          0x5100 /* GMBUS clock/device select register */
+#define GMBUS1          0x5104 /* GMBUS command/status register */
+#define GMBUS2          0x5108 /* GMBUS status register */
+#define GMBUS3          0x510C /* GMBUS data buffer register */
+#define GMBUS4          0x5110 /* GMBUS REQUEST_INUSE register */
+#define GMBUS5          0x5120 /* GMBUS 2-Byte Index register */
+#define GMBUS6          0x5124 /* GMBUS Clock divider */
+
+/*  GMBUS1 Bits */
+#define SW_CLR_INT      BIT31
+#define SW_RDY          BIT30
+#define ENT             BIT29
+#define STO             BIT27
+#define ENIDX           BIT26
+#define STA             BIT25
+
+/*  GMBUS2 Bits */
+#define INUSE           BIT15
+#define HW_WAIT         BIT14
+#define HW_TMOUT        BIT13
+#define HW_INT          BIT12
+#define HW_RDY          BIT11
+#define HW_BUS_ERR      BIT10
+#define GA              BIT9
+
+/*-----------------------------------------------------------------------------
+ * Clock Control and PM Register ( 06000h - 06FFFh )
+ *---------------------------------------------------------------------------*/
+#define VGA0_DIVISOR    0x06000  /* VGA 0  Divisor */
+#define VGA1_DIVISOR    0x06004  /* VGA 1 Divisor */
+#define VGA_PD          0x06010  /* VGA Post Divisor Select */
+#define DPLLACNTR       0x06014  /* Display PLL A Control */
+#define DPLLBCNTR       0x06018  /* Display PLL B Control */
+#define FPA0            0x06040  /* DPLL A Divisor 0 */
+#define FPA1            0x06044  /* DPLL A Divisor 1 */
+#define FPB0            0x06048  /* DPLL B Divisor 0 */
+#define FPB1            0x0604C  /* DPLL B Divisor 1 */
+
+#define DREFCLK         0x0
+#define TVCLKINBC       0x4000
+#define CLOCK_2X        0x40000000
+
+#define P2D_CG_DIS      0x06200  /* Clock Gating Disable */
+#define P3D_CG_DIS      0x06204  /* Clock Gating Disable */
+
+
+/*-----------------------------------------------------------------------------
+ * Display Palette Register Definitions (0A000h - 0AFFFh)
+ *---------------------------------------------------------------------------*/
+#define DPALETTE_A      0x0A000  /* Display Pipe A Palette */
+#define DPALETTE_B      0x0A800  /* Display Pipe B Palette */
+
+
+/*-----------------------------------------------------------------------------
+ * Display Pipeline / Port Register Definitions (60000h - 6FFFFh)
+ *---------------------------------------------------------------------------*/
+#define DP_OFFSET       0x60000  /* register group offset */
+#define PIPEA_TIMINGS   0x60000
+#define HTOTAL_A        0x60000  /* Pipe A Horizontal Total Register */
+#define ACTIVE_DISPLAY  0x7FF    /* bit [ 10:0 ] */
+#define HBLANK_A        0x60004  /* Pipe A Horizontal Blank Register */
+#define HSYNC_A         0x60008  /* Pipe A Horizontal Sync Register */
+#define VTOTAL_A        0x6000C  /* Pipe A Vertical Total Register */
+#define VBLANK_A        0x60010  /* Pipe A Vertical Blank Register */
+#define VSYNC_A         0x60014  /* Pipe A Vertical Sync Register */
+#define PIPEASRC        0x6001C  /* Pipe A Source Image Size Register */
+#define BCLRPAT_A       0x60020  /* Pipe A Border Color Pattern Register */
+#define CRCCTRLREDA     0x60050  /* Pipe A CRC Red Control Register */
+#define CRCCTRLGREENA   0x60054  /* Pipe A CRC Green Control Register */
+#define CRCCTRLBLUEA    0x60058  /* Pipe A CRC Blue Control Register */
+#define CRCCTRLRESA     0x6005C  /* Pipe A CRC Alpha Control Register */
+
+#define PIPEB_TIMINGS   0x61000
+#define HTOTAL_B        0x61000  /* Pipe B Horizontal Total Register */
+#define HBLANK_B        0x61004  /* Pipe B Horizontal Blank Register */
+#define HSYNC_B         0x61008  /* Pipe B Horizontal Sync Register */
+#define VTOTAL_B        0x6100C  /* Pipe B Vertical Total Register */
+#define VBLANK_B        0x61010  /* Pipe B Vertical Blank Register */
+#define VSYNC_B         0x61014  /* Pipe B Vertical Sync Register */
+#define PIPEBSRC        0x6101C  /* Pipe B Source Image Size Register */
+#define BCLRPAT_B       0x61020  /* Pipe B Border Color Pattern Register */
+#define CRCCTRLREDB     0x61050  /* Pipe B CRC Red Control Register */
+#define CRCCTRLGREENB   0x61054  /* Pipe B CRC Green Control Register */
+#define CRCCTRLBLUEB    0x61058  /* Pipe B CRC Blue Control Register */
+#define CRCCTRLRESB     0x6105C  /* Pipe B CRC Alpha Control Register */
+
+#define PORT_HPLUG_EN	0x61110  /* Port Hot Plug Enable */
+#define PORT_HPLUG_STAT 0x61114  /* Port Hot Plug Status */
+#define SDVOBCNTR       0x61140  /* Digital Display Port B Control */
+#define SDVOCCNTR       0x61160  /* Digital Display Port B Control */
+#define LVDSCNTR        0x61180  /* Digital Display Port Control */
+
+/* Panel Power Sequencing */
+#define LVDS_PNL_PWR_STS  0x61200  /* LVDS Panel Power Status Register */
+#define LVDS_PNL_PWR_CTL  0x61204  /* LVDS Panel Power Control Register */
+#define PP_ON_DELAYS      0x61208  /* Panel Power On Sequencing Delays */
+#define PP_OFF_DELAYS     0x6120C  /* Panel Power Off Sequencing Delays */
+#define PP_DIVISOR        0x61210  /* Panel Power Cycle Delay and Reference */
+
+/* Panel Fitting */
+#define PFIT_CONTROL      0x61230  /* Panel Fitting Control */
+#define PFIT_PGM_RATIOS   0x61234  /* Programmed Panel Fitting Ratios */
+#define PFIT_AUTO_RATIOS  0x61238  /* Programmed Panel Fitting Ratios */
+#define PFIT_INIT_PHASE   0x6123C  /* Programmed Panel Fitting Ratios */
+
+/* Backlight control */
+#define BLC_PWM_CTL       0x61254  /* Backlight PWM Control */
+#define BLM_HIST_CTL      0x61260  /* Image BLM Histogram Control */
+
+#define PORT_EN           BIT31
+#define PORT_PIPE_SEL     BIT30
+#define PORT_PIPE_SEL_POS 30
+#define PORT_PIPE_A       0      /* 0 = Pipe A */
+#define PORT_PIPE_B       BIT30  /* 1 = Pipe B */
+#define STALL_MASK        BIT29 + BIT28
+#define STALL_ENABLE      BIT28
+#define SYNC_MASK         BIT15 + BIT11 + BIT10 + BIT4 + BIT3
+#define SYNC_POLARITY     BIT15  /* 1 = Use VGA register */
+#define VSYNC_OUTPUT      BIT11
+#define HSYNC_OUTPUT      BIT10
+#define VSYNC_POLARITY    BIT4
+#define HSYNC_POLARITY    BIT3
+#define FP_DATA_ORDER     BIT14
+#define SUBDATA_ORDER     BIT6
+#define BORDER_EN         BIT7
+#define DISPLAY_EN        BIT2
+#define INTERLACED_BIT    0x00100000
+#define RGBA_BITS         0x00030000
+
+
+
+/*-----------------------------------------------------------------------------
+ * Display Pipeline A Register ( 70000h - 70024h )
+ *---------------------------------------------------------------------------*/
+#define PIPEA_SCANLINE_COUNT   0x70000  /* Pipe A Scan Line Count (RO) */
+#define PIPEA_SCANLINE_COMPARE 0x70004  /* Pipe A SLC Range Compare (RO) */
+#define PIPEA_CONF             0x70008  /* Pipe A Configuration */
+#define PIPE_STATUS_OFFSET     0x1C
+#define PIPEA_STAT             0x70024  /* Pipe A Display Status */
+#define PIPEA_DISP_ARB_CTRL    0x70030  /* Display Arbitration Control */
+#define FW_BLC_AB              0x70034
+#define FW_BLC_C               0x70038
+#define PIPEA_FRAME_HIGH       0x70040  /* Pipe A Frame Count High */
+#define PIPEA_FRAME_PIXEL      0x70044  /* Pipe A Frame Cnt Low & pixel count */
+
+#define PIPE_PIXEL_MASK        0x00ffffff
+#define PIPE_FRAME_HIGH_MASK   0x0000ffff
+#define PIPE_FRAME_LOW_MASK    0xff000000
+#define PIPE_FRAME_LOW_SHIFT   24
+
+
+/* following bit flag defs can be re-used for Pipe-B */
+#define PIPE_ENABLE       BIT31
+#define PIPE_LOCK         BIT25
+#define GAMMA_MODE        BIT24
+#define HOT_PLUG_EN       BIT26
+/* Setting this bit to a 1 in the PIPE{A|B}_STAT register, enables the
+ * consideration of vertical sync interrupts.
+ */
+#define VSYNC_STS_EN      BIT25
+/* Setting this bit to a 1 in the PIPE{A|B}_STAT register, enables the
+ * consideration of vertical blank interrupts.
+ */
+#define VBLANK_STS_EN     BIT17
+#define HOT_PLUG_STS      BIT10
+#define VSYNC_STS         BIT9
+#define VBLANK_STS        BIT1
+/* The following are "sticky" status bits in the PIPE{A|B}_STAT register.  They
+ * are cleared by writing a 1 to them.  Theres is code that reads a
+ * PIPE{A|B}_STAT register into a variable, then modifies the variable, and
+ * writes it back to the register.  These bits should be treated specially, so
+ * as not to inadvertantly clear the status bits, so that other code looking
+ * for those bits to be set won't miss it.
+ */
+#define PIPESTAT_STS_BITS ((unsigned long) BIT31 | BIT13 | BIT12 | BIT11 | \
+	VSYNC_STS | BIT8 | BIT5 | BIT4 | VBLANK_STS | BIT0)
+
+/*-----------------------------------------------------------------------------
+ * Hardware Cursor Register Definitions (70080h - 7009Ch)
+ *---------------------------------------------------------------------------*/
+#define CUR_A_CNTR        0x70080  /*Cursor A Control */
+#define CUR_B_CNTR        0x700C0
+#define CUR_BASE_OFFSET   0x4
+#define CUR_POS_OFFSET    0x8
+#define CUR_PAL0_OFFSET   0x10
+#define CUR_PAL1_OFFSET   0x14
+#define CUR_PAL2_OFFSET   0x18
+#define CUR_PAL3_OFFSET   0x1C
+
+/* Define these for ease of reference */
+#define CURSOR_A_BASE     CUR_A_CNTR + CUR_BASE_OFFSET
+#define CURSOR_A_POS      CUR_A_CNTR + CUR_POS_OFFSET
+#define CURSOR_A_PAL0     CUR_A_CNTR + CUR_PAL0_OFFSET
+#define CURSOR_A_PAL1     CUR_A_CNTR + CUR_PAL1_OFFSET
+#define CURSOR_A_PAL2     CUR_A_CNTR + CUR_PAL2_OFFSET
+#define CURSOR_A_PAL3     CUR_A_CNTR + CUR_PAL3_OFFSET
+#define CURSOR_B_BASE     CUR_B_CNTR + CUR_BASE_OFFSET
+#define CURSOR_B_POS      CUR_B_CNTR + CUR_POS_OFFSET
+#define CURSOR_B_PAL0     CUR_B_CNTR + CUR_PAL0_OFFSET
+#define CURSOR_B_PAL1     CUR_B_CNTR + CUR_PAL1_OFFSET
+#define CURSOR_B_PAL2     CUR_B_CNTR + CUR_PAL2_OFFSET
+#define CURSOR_B_PAL3     CUR_B_CNTR + CUR_PAL3_OFFSET
+
+
+/*-----------------------------------------------------------------------------
+ * VBIOS Software flags  00h - 0Fh
+ *---------------------------------------------------------------------------*/
+#define DSP_CHICKENBITS 0x70400  /* Chicken Bit */
+#define SWFABASE        0x70410  /* Software flags A Base Addr */
+#define SWF00           0x70410
+#define SWF01           0x70414
+#define SWF02           0x70418
+#define SWF03           0x7041C
+#define SWF04           0x70420
+#define SWF05           0x70424
+#define SWF06           0x70428
+#define SWF07           0x7042C
+#define SWF08           0x70430
+#define SWF09           0x70434
+#define SWF0A           0x70438
+#define SWF0B           0x7043C
+#define SWF0C           0x70440
+#define SWF0D           0x70444
+#define SWF0E           0x70448
+#define SWF0F           0x7044C
+
+
+/*-----------------------------------------------------------------------------
+ * Display Pipeline B Register ( 71000h - 71024h )
+ *---------------------------------------------------------------------------*/
+#define PIPEB_SCANLINE_COUNT   0x71000 /* Pipe B Disp Scan Line Count Reg */
+#define PIPEB_SCANLINE_COMPARE 0x71004 /* Pipe B Disp Scan Line Cnt Range Cmp */
+#define PIPEB_CONF             0x71008 /* Pipe B Pixel Pipeline Config Reg */
+#define PIPEB_STAT             0x71024 /* Display Status Select Register */
+#define PIPEB_FRAME_HIGH       0x71040 /* Pipe B Frame Count High */
+#define PIPEB_FRAME_PIXEL      0x71044 /* Pipe B Frame Cnt Low and pixel cnt */
+
+
+#define VBLANK_EVN_STS_EN   BIT20
+#define VBLANK_ODD_STS_EN   BIT21
+#define VBLANK_EVN_STS      BIT4
+#define VBLANK_ODD_STS      BIT5
+
+
+/*-----------------------------------------------------------------------------
+ * Display Plane B Register Definitions (71180h - 71188h)
+ *---------------------------------------------------------------------------*/
+#define DSPBFLIP        0x7117C  /* Display B Async flip */
+#define DSPBCNTR        0x71180  /* Display Plane B */
+#define DSPBADDR        0x71184  /* Display B Start Address */
+#define DSPBSTRIDE      0x71188  /* Display B Stride */
+#define DSPBPOS         0x7118C  /* Display B Sprite Offset */
+#define DSPBSIZE        0x71190  /* Display B Sprite Size */
+#define DSPBKEYVAL      0x71194  /* Sprite color key value */
+#define DSPBKEYMASK     0x71198  /* Sprite color key mask */
+
+
+
+/*-----------------------------------------------------------------------------
+ * Source Format Definition for DSPxCNTR
+ *---------------------------------------------------------------------------*/
+#define DSPxCNTR_ARGB_8888			0x1C000000
+#define DSPxCNTR_RGB_8888			0x18000000
+#define DSPxCNTR_RGB_565			0x14000000
+#define DSPxCNTR_RGB_555			0x10000000
+#define DSPxCNTR_RGB_8				0x08000000
+#define DSPxCNTR_SRC_FMT_MASK			0x3C000000 /*mask for above*/
+
+
+/*-----------------------------------------------------------------------------
+ * VBIOS Software flags  10h - 1Fh
+ *---------------------------------------------------------------------------*/
+#define SWFBBASE        0x71410  /* Software flags B Base Addr */
+#define SWF10           0x71410
+#define SWF11           0x71414
+#define SWF12           0x71418
+#define SWF13           0x7141C
+#define SWF14           0x71420
+#define SWF15           0x71424
+#define SWF16           0x71428
+#define SWF17           0x7142C
+#define SWF18           0x71430
+#define SWF19           0x71434
+#define SWF1A           0x71438
+#define SWF1B           0x7143C
+#define SWF1C           0x71440
+#define SWF1D           0x71444
+#define SWF1E           0x71448
+#define SWF1F           0x7144C
+
+
+/*-----------------------------------------------------------------------------
+ * Display Plane C Register Definitions (72180h - 72188h)
+ *---------------------------------------------------------------------------*/
+#define DSPCCNTR        0x72180  /* Display Plane C */
+#define DSPCADDR        0x72184  /* Display C Start Address */
+#define DSPCSTRIDE      0x72188  /* Display C Stride */
+#define DSPCPOS         0x7218C  /* Display C Position */
+#define DSPCSIZE        0x72190  /* Display C Size */
+#define DSPCKEYMINVAL   0x72194  /* Sprite color key Min */
+#define DSPCKEYMASK     0x72198  /* Sprite color key mask */
+#define DSPCKEYMAXVAL   0x721A0  /* Display C Sprint color key Max */
+
+#define DCLRC0          0x721D0  /* Display C Color Correction 0 */
+#define DCLRC1          0x721D4  /* Display C Color Correction 1 */
+#define DPYC_GAMC5      0x721E0  /* Display C Gamma Correction 5 */
+#define DPYC_GAMC4      0x721E4  /* Display C Gamma Correction 4 */
+#define DPYC_GAMC3      0x721E8  /* Display C Gamma Correction 3 */
+#define DPYC_GAMC2      0x721EC  /* Display C Gamma Correction 2 */
+#define DPYC_GAMC1      0x721F0  /* Display C Gamma Correction 1 */
+#define DPYC_GAMC0      0x721F4  /* Display C Gamma Correction 0 */
+
+#define PLANE_ENABLE    BIT31
+#define GAMMA_ENABLE    BIT30
+#define BPP_MASK        BIT29 + BIT28 + BIT27 + BIT26
+#define BPP_POS         26
+#define STEREO_ENABLE   BIT25
+#define PIPE_SEL        BIT24
+#define PIPE_SEL_POS    24
+#define PIXEL_MULTIPLY  BIT21 + BIT20
+#define STEREO_POLARITY BIT18
+
+/* Common offsets for all Display Pipeline registers */
+#define DSP_START_OFFSET 0x04  /* Offset from the control reg */
+#define DSP_STRIDE_OFFSET 0x08  /* Offset from the control reg */
+#define DSP_SIZE_OFFSET   0x10  /* Offset from the control reg */
+
+
+
+/*-----------------------------------------------------------------------------
+ * VGA Display Plane Control Register Definitions (71400h)
+ *---------------------------------------------------------------------------*/
+#define VP00             0x71400
+#define VGACNTRL         0x71400  /* VGA Display Plane Control Register */
+#define VGA_DOUBLE       BIT30
+#define VGA_PIPE         BIT29
+#define VGA_CENTER_MASK  BIT25 + BIT24
+#define VGA_CENTER_1     BIT25
+#define VGA_CENTER_0     BIT24
+#define VGA_PAL_READ     BIT23
+#define VGA_PAL_MASK     BIT22 + BIT21
+#define VGA_PALA_DISABLE BIT22
+#define VGA_PALB_DISABLE BIT21
+#define DAC_8_BIT	     BIT20
+#define VGA_8_DOT	     BIT18
+
+#define ADD_ID           0x71408  /* ADD Card ID Register*/
+
+#define OVADD            0x30000  /* Overlay Control */
+
+/*-----------------------------------------------------------------------------
+ * Software Flag Registers (71410h - 71428h)
+ *---------------------------------------------------------------------------*/
+
+/* Map old software flag names to their new Gen4 names */
+#define SF00  SWF10
+#define SF01  SWF11
+#define SF02  SWF12
+#define SF03  SWF13
+#define SF04  SWF14
+#define SF05  SWF15
+#define SF06  SWF16
+
+
+
+/*-----------------------------------------------------------------------------
+ * Scratch register to be used as additional parameter in SMI
+ *---------------------------------------------------------------------------*/
+#define SCRATCH_SWF6         0x71428
+
+/*-----------------------------------------------------------------------------
+ * Miscellaneous registers
+ ----------------------------------------------------------------------------*/
+#define HW_ST_PAGE_ADDR      0x02080
+
+
+/*-----------------------------------------------------------------------------
+ * GMBUS : I2C Bus Types
+ ----------------------------------------------------------------------------*/
+#define GMBUS_ANALOG_DDC    1
+#define GMBUS_INT_LVDS_DDC  2
+
+#define GMBUS_DVO_REG       3
+
+#define GMBUS_DVOB_DDC      4
+#define GMBUS_DVOC_DDC      5
+
+#endif /* _REGS_H_ */
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/sgx.h b/drivers/gpu/drm/emgd/emgd/include/plb/sgx.h
new file mode 100644
index 0000000..b882efc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/sgx.h
@@ -0,0 +1,217 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sgx.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  These are the defines specific to the SGX engine code.
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _SGX_H
+#define _SGX_H
+
+
+/* ---------------------------------------------------------*/
+/* MACROS */
+/* ---------------------------------------------------------*/
+#ifndef BUG_ON
+#define BUG_ON(_cond)
+#endif
+
+#ifndef BUG
+#define BUG()
+#endif
+
+
+/* ---------------------------------------------------------*/
+/* DEFINES*/
+/* ---------------------------------------------------------*/
+/* PSB SGX Memory buffer types */
+/* FIXME! - rename 'DRM' prefix to 'SGX'
+ * if we start using this */
+#define DRM_BO_MEM_LOCAL                        0
+#define DRM_BO_MEM_TT                           1
+#define DRM_BO_MEM_VRAM                         2
+#define DRM_BO_MEM_PRIV0                        3
+#define DRM_BO_MEM_PRIV1                        4
+#define DRM_BO_MEM_PRIV2                        5
+#define DRM_BO_MEM_PRIV3                        6
+#define DRM_BO_MEM_PRIV4                        7
+#define DRM_BO_MEM_TYPES                        8
+		/* For now. */
+#define DRM_BO_LOCK_UNLOCK_BM                   (1 << 0)
+#define DRM_BO_LOCK_IGNORE_NO_EVICT             (1 << 1)
+
+/* GMM APERTURE FUNCTIONAL SEGMENTATION
+ * - BEWARE!!!! we are not using this kind
+ *   of pre-allocated slots in IEGD arch
+ *   so this should remain commented!!??
+ *
+#define PSB_VDC_OFFSET                          0x00000000
+#define PSB_VDC_SIZE                            0x000080000
+#define PSB_SGX_SIZE                            0x8000
+#define PSB_SGX_OFFSET                          0x00040000
+#define PSB_MMIO_RESOURCE                       0
+#define PSB_GATT_RESOURCE                       2
+#define PSB_GTT_RESOURCE                        3
+#define PSB_GMCH_CTRL                           0x52
+#define PSB_BSM                                 0x5C
+#define _PSB_GMCH_ENABLED                       0x4
+#define PSB_PGETBL_CTL                          0x2020
+#define _PSB_PGETBL_ENABLED                     0x00000001
+#define PSB_SGX_2D_SLAVE_PORT                   0x4000
+#define PSB_TT_PRIV0_LIMIT                      (256*1024*1024)
+#define PSB_TT_PRIV0_PLIMIT                     (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT)
+#define PSB_NUM_VALIDATE_BUFFERS                512
+#define PSB_MEM_KERNEL_START                    0x10000000
+#define PSB_MEM_PDS_START                       0x20000000
+#define PSB_MEM_RASTGEOM_START                  0x30000000
+#define PSB_MEM_MMU_START                       0x40000000
+*/
+
+#define XPSB_LOCAL_SIZE                         4096
+#define XPSB_SPROG_SIZE                         1024
+#define XPSB_GEOM_SIZE                          8192
+
+#define PSB_HW_COOKIE_SIZE                      16
+#define PSB_HW_FEEDBACK_SIZE                    8
+
+#define PAGE_SHIFT                              12
+#define PSB_DPM_BUFFER_PAGES                    ((10*1024*1024) >> PAGE_SHIFT)
+#define PSB_DPM_TABLE_SIZE                      0x40000
+#define PSB_PARAM_PAGE_SHIFT                    PAGE_SHIFT
+#define PSB_PARAM_PAGE_SIZE                     PAGE_SIZE
+#define PSB_MIN_NONGLOBAL_PAGES                 1024
+#define PSB_PLM(_val, _base)			\
+		(((_val) << (_base ## _SHIFT)) & (_base ## _MASK))
+
+/*
+ * Number of registers in a PDS attribute chunk.
+ */
+#define PSB_PDS_CHUNK_SIZE		                (32)
+#define PSB_PDS_CHUNK_SIZE_SHIFT	            (5)
+
+/*
+ * Number of registers reserved for output registers.
+ */
+#define PSB_USE_NUM_OUTPUT_REGISTERS            (384)
+
+/*
+ * Total number of USE registers.
+ */
+
+#define PSB_USE_NUM_UNIFIED_REGISTERS	        (2048)
+/*
+ *
+ */
+
+#define PSB_USE_DEFAULT_TEMP_REG_COUNT	        (384)
+#define PSB_USE_DEFAULT_TEMP_GRAN	            (4)
+#define PSB_USE_DEFAULT_TEMP_REG_INIT	        (24)
+#define PSB_USE_DEFAULT_ATTRIB_REG_COUNT        (2048 - 384 * 2) /* 1280 */
+
+
+/* ---------------------------------------------------------*/
+/* STRUCTURES */
+/* ---------------------------------------------------------*/
+struct drm_psb_xhw_arg {
+	unsigned long op;
+	int ret;
+	unsigned long irq_op;
+	unsigned long issue_irq;
+	unsigned long cookie[PSB_HW_COOKIE_SIZE];
+	union {
+		struct {
+			unsigned long w;
+			unsigned long h;
+			unsigned long size;
+			unsigned long clear_p_start;
+			unsigned long clear_num_pages;
+		} si;
+		struct {
+			unsigned long fire_flags;
+			unsigned long hw_context;
+			unsigned long offset;
+			unsigned long engine;
+			unsigned long flags;
+			unsigned long feedback[PSB_HW_FEEDBACK_SIZE];
+		} sb;
+		struct {
+			unsigned long pages;
+			unsigned long size;
+		} bi;
+		struct {
+			unsigned long bca;
+			unsigned long rca;
+			unsigned long flags;
+		} oom;
+	} arg;
+};
+struct pclosed_vopt
+{
+    int fix_hw_brn_20267;
+    int fix_hw_brn_20696;
+    int fix_hw_brn_20852;
+    int fix_hw_brn_21024;
+    int fix_hw_brn_21049;
+    int fix_hw_brn_21117;
+    int fix_hw_brn_21158;
+    int fix_hw_brn_21183;
+    int fix_hw_brn_21226;
+    int fix_hw_brn_21227;
+    int fix_hw_brn_21301;
+    int fix_hw_brn_21329;
+    int fix_hw_brn_21351;
+    int fix_hw_brn_21369;
+    int fix_hw_brn_21387;
+    int fix_hw_brn_21246;
+    int fix_hw_brn_21500;
+    int fix_hw_brn_21551;
+    int fix_hw_brn_21592;
+    int fix_hw_brn_21652;
+    int fix_hw_brn_21788;
+    int fix_hw_brn_21826;
+    int fix_hw_brn_21878;
+    int fix_hw_brn_21893;
+    int fix_hw_brn_21934;
+    int fix_hw_brn_21986;
+    int fix_hw_brn_22048;
+    int fix_hw_brn_22107;
+    int fix_hw_brn_22111;
+    int fix_hw_brn_22136;
+    int fix_hw_brn_22162;
+    int fix_hw_brn_22329;
+    int fix_hw_brn_22336;
+    int fix_hw_brn_22364;
+    int fix_hw_brn_22117;
+    int fix_hw_brn_22380;
+    int fix_hw_brn_22391;
+    int fix_hw_brn_22393;
+    int fix_hw_brn_22462;
+    int fix_hw_brn_22563;
+    int fix_hw_brn_22666;
+    int fix_hw_brn_23281;
+};
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/state3d.h b/drivers/gpu/drm/emgd/emgd/include/plb/state3d.h
new file mode 100644
index 0000000..68f4a80
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/state3d.h
@@ -0,0 +1,398 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: state3d.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file is an inter-module header file for manipulating the 3D
+ *  State variables.
+ *-----------------------------------------------------------------------------
+ */
+/*
+ * This is referenced from Napa code. For Poulsbo, the HW spec may be
+ * different. Be ready for the new change.
+ */
+
+#ifndef _STATE3D_H
+#define _STATE3D_H
+
+#include <plb/appcontext.h>
+
+/* The dispatch table */
+typedef struct _state3d_dispatch_plb_t {
+	int lsi1_s2_needs_s3;     /* Does LSI1 S2 also require S3? */
+	int lsi2_s3_830_845;
+} state3d_dispatch_plb_t;
+
+/* The array of buffer infos are used for these purposes */
+#define COLOR_BUFFER_INDEX 0
+#define DEPTH_BUFFER_INDEX 1
+#define AUX0_BUFFER_INDEX  2
+#define AUX1_BUFFER_INDEX  3
+#define INTRA_BUFFER_INDEX 4
+
+typedef struct _state3d_buffer_info_plb {
+	union {
+		struct {
+			unsigned long pitch :14;
+			unsigned long :7;
+			unsigned long tile_walk :1;
+			unsigned long tiled :1;
+			unsigned long fenced :1;
+			unsigned long buffer_id :4;
+			unsigned long aux_id :1;
+			unsigned long :3;
+		};
+		unsigned long dw1;
+	};
+	union {
+		unsigned long base;
+		unsigned long dw2;
+	};
+	unsigned long mod;
+} state3d_buffer_info_plb_t;
+
+typedef struct _state3d_dest_buffer_vars_plb {
+	union {
+		struct {
+			unsigned long vert_offset  :1;
+			unsigned long vert_stride  :1;
+			unsigned long depth_format :3;
+			unsigned long :1;
+			unsigned long depth_component :1;
+			unsigned long :1;
+			unsigned long color_format :4;
+			unsigned long write_select :3;
+			unsigned long :1;
+			unsigned long vert_bias  :4;
+			unsigned long horiz_bias :4;
+			unsigned long dither_disable :1;
+			unsigned long gamma_blend_enable :1;
+			unsigned long dither_patten :2;
+			unsigned long :4;
+		};
+		unsigned long dw1;
+	};
+	unsigned long mod;
+} state3d_dest_buffer_vars_plb_t;
+
+typedef struct _state3d_vertex_buffer {
+	unsigned long addr;
+	unsigned long width;
+	unsigned long pitch;
+	unsigned long enable;
+	unsigned long mod;
+} state3d_vertex_buffer_t;
+
+#define VERTEX_BUFFER_ADDR_MODIFIED    0x1
+#define VERTEX_BUFFER_WIDTH_MODIFIED   0x2
+#define VERTEX_BUFFER_PITCH_MODIFIED   0x4
+#define VERTEX_BUFFER_ENABLE_MODIFIED  0x8
+
+typedef struct _state3d_texture_coord_set {
+	unsigned long format;
+	unsigned long enable;
+	unsigned long mod;
+} state3d_texture_coord_set_t;
+
+typedef struct _state3d_coord_set {
+	unsigned long transform_enable;
+	unsigned long normalized_coords;
+	unsigned long source;
+	unsigned long type;
+	unsigned long addr_v_control_mode;
+	unsigned long addr_u_control_mode;
+	unsigned long mod;
+} state3d_coord_set_t;
+
+typedef struct _state3d_texel_stream {
+	unsigned long modification_enable;
+	unsigned long modifier_unit_index;
+	unsigned long coord_select;
+	unsigned long map_select;
+	unsigned long mod;
+} state3d_texel_stream_t;
+
+#define MODIFICATION_ENABLE_MODIFIED 0x1
+#define MODIFIER_UNIT_INDEX_MODIFIED 0x2
+#define COORD_SELECT_MODIFIED        0x4
+#define MAP_SELECT_MODIFIED          0x8
+
+typedef struct _state3d_texel_modifier {
+	unsigned long texel_stream_index;
+	unsigned long bump_param_table_index;
+	unsigned long enable;
+	unsigned long mod;
+} state3d_texel_modifier_t;
+
+#define TEXEL_STREAM_INDEX_MODIFIED     0x1
+#define BUMP_PARAM_TABLE_INDEX_MODIFIED 0x2
+#define ENABLE_MODIFIED                 0x4
+
+/*
+ * These can be changed with the LOAD_STATE_IMMEDIATE_1 S3 Instruction.
+ */
+typedef struct _state3d_imm1_state3 {
+	unsigned long point_width;
+	unsigned long line_width;
+	unsigned long alpha_shade_mode;
+	unsigned long fog_shade_mode;
+	unsigned long specular_shade_mode;
+	unsigned long color_shade_mode;
+	unsigned long cull_mode;
+	unsigned long point_width_present;
+	unsigned long specular_color_present; /* And Fog Factor */
+	unsigned long diffuse_color_present;
+	unsigned long depth_offset_present;
+	unsigned long position_mask;
+	unsigned long specular_add_enable;
+	unsigned long fog_enable;
+	unsigned long local_depth_bias_enable;
+	unsigned long sprite_point_enable;
+	unsigned long antialiasing_enable;
+	unsigned long mod;
+} state3d_imm1_state3_t;
+
+#define POINT_WIDTH_MODIFIED             0x1
+#define LINE_WIDTH_MODIFIED              0x2
+#define ALPHA_SHADE_MODE_MODIFIED        0x4
+#define FOG_SHADE_MODE_MODIFIED          0x8
+#define SPECULAR_SHADE_MODE_MODIFIED     0x10
+#define COLOR_SHADE_MODE_MODIFIED        0x20
+#define CULL_MODE_MODIFIED               0x40
+#define POINT_WIDTH_PRESENT_MODIFIED     0x80
+#define SPECULAR_COLOR_PRESENT_MODIFIED  0x100
+#define DIFFUSE_COLOR_PRESENT_MODIFIED   0x200
+#define DEPTH_OFFSET_PRESENT_MODIFIED    0x400
+#define POSITION_MASK_MODIFIED           0x800
+#define SPECULAR_ADD_ENABLE_MODIFIED     0x1000
+#define FOG_ENABLE_MODIFIED              0x2000
+#define LOCAL_DEPTH_BIAS_ENABLE_MODIFIED 0x4000
+#define SPRITE_POINT_ENABLE_MODIFIED     0x8000
+#define ANTIALAISING_ENABLE_MODIFIED     0x10000
+
+/*
+ * These can be changed with the LOAD_STATE_IMMEDIATE_1 S7 Instruction.
+ */
+typedef struct _state3d_imm1_state7 {
+	unsigned long global_depth_bias;
+	unsigned long stencil_reference_value;
+	unsigned long stencil_test_function;
+	unsigned long stencil_fail_op;
+	unsigned long stencil_pass_depth_fail_op;
+	unsigned long stencil_pass_depth_pass_op;
+	unsigned long stencil_buffer_write_enable;
+	unsigned long stencil_test_enable;
+	unsigned long color_dither_enable;
+	unsigned long logic_op_enable;
+	unsigned long mod;
+} state3d_imm1_state7_t;
+
+#define GLOBAL_DEPTH_BIAS_MODIFIED           0x1
+#define STENCIL_REFERENCE_VALUE_MODIFIED     0x2
+#define STENCIL_TEST_FUNCTION_MODIFIED       0x4
+#define STENCIL_FAIL_OP_MODIFIED             0x8
+#define STENCIL_PASS_DEPTH_FAIL_OP_MODIFIED  0x10
+#define STENCIL_PASS_DEPTH_PASS_OP_MODIFIED  0x20
+#define STENCIL_BUFFER_WRITE_ENABLE_MODIFIED 0x40
+#define STENCIL_TEST_ENABLE_MODIFIED         0x80
+#define COLOR_DITHER_ENABLE_MODIFIED         0x100
+#define LOGIC_OP_ENABLE_MODIFIED             0x200
+
+/*
+ * These can be changed with the LOAD_STATE_IMMEDIATE_1 S8 Instruction.
+ */
+typedef struct _state3d_imm1_state8 {
+	unsigned long alpha_test_enable;
+	unsigned long alpha_test_function;
+	unsigned long alpha_reference_value;
+	unsigned long depth_test_enable;
+	unsigned long depth_test_function;
+	unsigned long color_buffer_blend_enable;
+	unsigned long color_blend_function;
+	unsigned long source_blend_factor;
+	unsigned long destination_blend_factor;
+	unsigned long depth_buffer_write_enable;
+	unsigned long color_buffer_write_enable;
+	unsigned long triangle_provoking_vertex_select;
+} state3d_imm1_state8_t;
+
+typedef struct _state3d_imm2_tms0 {
+	unsigned long tm_map_base_addr;
+	unsigned long tm_utilize_fence_regs;
+	unsigned long reverse_gamma_enable;
+} state3d_imm2_tms0_t;
+
+typedef struct _state3d_imm2_tms1 {
+	unsigned long tm_height;
+	unsigned long tm_width;
+	unsigned long tm_palette_select;
+	unsigned long tm_surface_format;
+	unsigned long tm_texel_format;
+	unsigned long tm_color_space_conversion_enable;
+	unsigned long tm_tiled_surface;
+	unsigned long tm_tile_walk;
+} state3d_imm2_tms1_t;
+
+typedef struct _state3d_imm2_tms2 {
+	unsigned long tm_dword_pitch;
+	unsigned long tm_cube_face_enables;
+	unsigned long tm_map_format;
+	unsigned long tm_vertical_line_stride;
+	unsigned long tm_vertical_line_stride_offset;
+	unsigned long tm_output_channel_selection;
+	unsigned long tm_base_mip_level;
+	unsigned long tm_lod_preclamp_enable;
+} state3d_imm2_tms2_t;
+
+typedef struct _state3d_imm2_tms3 {
+	unsigned long tm_mip_mode_filter;
+	unsigned long tm_mag_mode_filter;
+	unsigned long tm_min_mode_filter;
+	unsigned long tm_texture_lod_bias;
+	unsigned long tm_colorkey_enable;
+	unsigned long tm_chromakey_enable;
+	unsigned long tm_maximum_mip_level;
+	unsigned long tm_minimum_mip_level;
+	unsigned long tm_kill_pixel_enable;
+	unsigned long tm_keyed_texture_filter_mode;
+} state3d_imm2_tms3_t;
+
+typedef struct _state3d_imm2_tms4 {
+	unsigned long tm_default_color;
+} state3d_imm2_tms4_t;
+
+/*
+ * All pointers may be NULL. If so defaults should be assumed.
+ */
+typedef struct _state3d {
+	igd_surface_t color_buffer;
+	igd_surface_t depth_buffer;
+	state3d_vertex_buffer_t vertex_buffer[2];
+	state3d_texture_coord_set_t texture_coord_set[8];
+	unsigned long texture_coord_count;
+	state3d_imm1_state3_t imm1_s3;
+	state3d_coord_set_t coord_set[4];
+	state3d_texel_modifier_t texel_modifier[2];
+	state3d_texel_stream_t texel_stream[4];
+	state3d_imm1_state7_t imm1_s7;
+	state3d_imm1_state8_t imm1_s8;
+	state3d_imm2_tms0_t imm2_tms0[4];
+	state3d_imm2_tms1_t imm2_tms1[4];
+	state3d_imm2_tms2_t imm2_tms2[4];
+	state3d_imm2_tms3_t imm2_tms3[4];
+	state3d_imm2_tms4_t imm2_tms4[4];
+	state3d_buffer_info_plb_t buffer_info[5];
+	state3d_dest_buffer_vars_plb_t buffer_vars;
+	unsigned long mod;
+	state3d_dispatch_plb_t *dispatch;
+} state3d_t, state3d_plb_t;
+
+#define IMM1_MODIFIED    0x1ff
+#define IMM1_S0_MODIFIED 0x1
+#define IMM1_S1_MODIFIED 0x2
+#define IMM1_S2_MODIFIED 0x4
+#define IMM1_S3_MODIFIED 0x8
+#define IMM1_S4_MODIFIED 0x10
+#define IMM1_S5_MODIFIED 0x20
+#define IMM1_S6_MODIFIED 0x40
+#define IMM1_S7_MODIFIED 0x80
+#define IMM1_S8_MODIFIED 0x100
+#define IMM2_MODIFIED     0xf0000
+#define IMM2_TM0_MODIFIED 0x10000
+#define IMM2_TM1_MODIFIED 0x20000
+#define IMM2_TM2_MODIFIED 0x40000
+#define IMM2_TM3_MODIFIED 0x80000
+
+#define LOAD_S0 0x1
+#define LOAD_S1 0x2
+#define LOAD_S2 0x4
+#define LOAD_S3 0x8
+#define LOAD_S4 0x10
+#define LOAD_S5 0x20
+#define LOAD_S6 0x40
+#define LOAD_S7 0x80
+#define LOAD_S8 0x100
+#define LOAD_TM  0xf0000
+#define LOAD_TM0 0x10000
+#define LOAD_TM1 0x20000
+#define LOAD_TM2 0x40000
+#define LOAD_TM3 0x80000
+
+#define STATE3D_SET_ALPHA_TEST_ENABLE(s, v) \
+    s->imm1_s8.alpha_test_enable = (v & 1); \
+    s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_ALPHA_TEST_FUNCTION(s, v) \
+    s->imm1_s8.alpha_test_function = (v & 7); \
+    s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_ALPHA_REFERENCE_VALUE(s, v) \
+    s->imm1_s8.alpha_reference_value = (v & 0xf); \
+    s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_DEPTH_TEST_ENABLE(s, v) \
+    s->imm1_s8.depth_test_enable = (v & 1); \
+    s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_DEPTH_TEST_FUNCTION(s, v) \
+    s->imm1_s8.depth_test_function = (v & 7); \
+    s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_COLOR_BUFFER_BLEND_ENABLE(s, v) \
+    s->imm1_s8.color_buffer_blend_enable = (v & 1); \
+    s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_COLOR_BLEND_FUNCTION(s, v) \
+    s->imm1_s8.color_blend_function = (v & 7); \
+    s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_SOURCE_BLEND_FACTOR(s, v) \
+    s->imm1_s8.source_blend_factor = (v & 0xf); \
+    s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_DESTINATION_BLEND_FACTOR(s, v) \
+    s->imm1_s8.destination_blend_factor = (v & 0xf); \
+    s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_DEPTH_BUFFER_WRITE_ENABLE(s, v) \
+    s->imm1_s8.depth_buffer_write_enable = (v & 1); \
+    s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_COLOR_BUFFER_WRITE_ENABLE(s, v) \
+    s->imm1_s8.color_buffer_write_enable = (v & 1); \
+    s->mod |= IMM1_S8_MODIFIED;
+
+#define STATE3D_SET_TRIANGLE_PROVOKING_VERTEX_SELECT(s, v) \
+    s->imm1_s8.triangle_provoking_vertex_select = (v & 3); \
+    s->mod |= IMM1_S8_MODIFIED;
+
+
+#define STATE3D(ac) ((state3d_t *)((appcontext_plb_t *)ac)->state3d)
+
+int state3d_update_plb(igd_command_t **in, appcontext_t *appcontext);
+int state3d_update_size(appcontext_t *appcontext);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/plb/state3d_plb.h b/drivers/gpu/drm/emgd/emgd/include/plb/state3d_plb.h
new file mode 100644
index 0000000..37327bc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/plb/state3d_plb.h
@@ -0,0 +1,1299 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: state3d_plb.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file is an inter-module header file for manipulating the 3D
+ *  State variables.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _STATE3D_PLB_H
+#define _STATE3D_PLB_H
+
+#include <plb/appcontext.h>
+
+typedef struct _state3d_anti_aliasing_plb {
+	union {
+		struct {
+			unsigned int :6;
+			unsigned int line_aa_region_width :2;
+			unsigned int line_aa_region_width_mod_en :1;
+			unsigned int :5;
+			unsigned int line_end_cap_aa_region_width :2;
+			unsigned int line_end_cap_aa_region_width_mod_en :1;
+			unsigned int :15;
+		};
+		unsigned int dw0;
+	};
+	unsigned int updated;
+
+} state3d_anti_aliasing_plb_t;
+
+#define STATE3D_ANTI_ALIASING_UPDATED_PLB	1
+#define STATE3D_ANTI_ALIASING_DWORD_COUNT_PLB 	1
+
+typedef struct _state3d_backface_stencil_ops_plb {
+	union {
+		struct {
+			unsigned int double_sided_en :1;
+			unsigned int double_sided_en_mod_en :1;
+			unsigned int pass_depth_pass_op :3;
+			unsigned int pass_depth_fail_op :3;
+			unsigned int fail_op :3;
+			unsigned int test_function :3;
+			unsigned int multiple_mod_en :1;
+			unsigned int ref_val :8;
+			unsigned int ref_val_mod_en :1;
+			unsigned int :8;
+		};
+		unsigned int dw0;
+	};
+	unsigned int updated;
+} state3d_backface_stencil_ops_plb_t;
+#define STATE3D_BACKFACE_STENCIL_OPS_UPDATED_PLB	1
+#define STATE3D_BACKFACE_STENCIL_OPS_DWORD_COUNT_PLB	1
+
+typedef struct _state3d_backface_stencil_masks_plb {
+	union {
+		struct {
+			unsigned int write_mask :8;
+			unsigned int test_mask :8;
+			unsigned int write_mask_mod_en :1;
+			unsigned int test_mask_mod_en :1;
+			unsigned int :14;
+		};
+		unsigned int dw0;
+	};
+	unsigned int updated;
+} state3d_backface_stencil_masks_plb_t;
+#define STATE3D_BACKFACE_STENCIL_MASK_UPDATED_PLB	1
+#define STATE3D_BACKFACE_STENCIL_MASK_DWORD_COUNT_PLB	1
+
+/* FIXME: Details are ignored in this struct */
+typedef struct _state3d_bin_control_plb {
+	unsigned int dw0;
+	unsigned int dw1;
+	unsigned int dw2;
+	unsigned int dw3;
+	unsigned int dw4;
+	unsigned int dw5;
+	unsigned int updated;
+} state3d_bin_control_plb_t;
+#define STATE3D_BIN_CONTROL_UPDATED_PLB		1
+#define STATE3D_BIN_CONTROL_DWORD_COUNT_PLB	6
+
+typedef struct _state3d_buffer_info_plb {
+	unsigned int dw0;
+	union {
+		struct {
+			unsigned int :2;
+			unsigned int buffer_pitch :12;
+			unsigned int :7;
+			unsigned int tile_walk :1;
+			unsigned int tiled_surface :1;
+			unsigned int util_fence_regs :1;
+			unsigned int buffer_id :4;
+			unsigned int aux_buffer_id :1;
+			unsigned int :3;
+		};
+		unsigned int dw1;
+	};
+	union {
+		struct {
+			unsigned int :2;
+			unsigned int buffer_base_addr :26;
+		};
+		unsigned int dw2;
+	};
+	unsigned int updated;
+} state3d_buffer_info_plb_t;
+#define STATE3D_BUFFER_INFO_UPDATED_PLB		1
+#define STATE3D_BUFFER_INFO_DWORD_COUNT_PLB	3
+#define STATE3D_BUFFER_INFO_BUFFERID_COLOR_BACK			0x03
+#define STATE3D_BUFFER_INFO_BUFFERID_COLOR_AUX			0x04
+#define STATE3D_BUFFER_INFO_BUFFERID_COLOR_MC_INTRA_CORR	0x05
+#define STATE3D_BUFFER_INFO_BUFFERID_DEPTH			0x07
+
+typedef struct _state3d_chroma_key_plb {
+	union {
+		struct {
+			unsigned int :30;
+			unsigned int table_index :2;
+		};
+		unsigned int dw1;
+	};
+	union {
+		unsigned int lo_val;
+		unsigned int dw2;
+	};
+	union {
+		unsigned int hi_val;
+		unsigned int dw3;
+	};
+	unsigned int updated;
+} state3d_chroma_key_plb_t;
+#define STATE3D_CHROMA_KEY_UPDATED_PLB		1
+#define STATE3D_CHROMA_KEY_DWORD_COUNT_PLB	4
+
+typedef struct _state3d_clear_parameters_plb {
+	union {
+		struct {
+		unsigned int stencil_write_en :1;
+		unsigned int depth_buffer_write_en :1;
+		unsigned int color_buffer_write_en :1;
+			unsigned int :13;
+			unsigned int clear_primitive_type :1;
+			unsigned int :15;
+		};
+		unsigned int dw1;
+        };
+	union {
+		unsigned int	clear_color_buffer_val;
+		unsigned int dw2;
+	};
+	union {
+	unsigned int	clear_depth_buffer_val;
+		unsigned int dw3;
+	};
+	union {
+	unsigned int	clear_color;
+		unsigned int dw4;
+	};
+	union {
+	unsigned int	clear_depth;
+		unsigned int dw5;
+	};
+	union {
+		struct {
+		unsigned int clear_stencil :8;
+			unsigned int :24;
+		};
+		unsigned int dw6;
+	};
+	unsigned int updated;
+} state3d_clear_parameters_plb_t;
+#define STATE3D_CLEAR_PARAMETERS_UPDATED_PLB		1
+#define STATE3D_CLEAR_PARAMETERS_DWORD_COUNT_PLB	7
+
+typedef struct _state3d_constant_blend_color_plb {
+	union {
+		unsigned int color;
+		unsigned int dw1;
+	};
+	unsigned int updated;
+} state3d_constant_blend_color_plb_t;
+#define STATE3D_CONSTANT_BLEND_COLOR_UPDATED_PLB	1
+#define STATE3D_CONSTANT_BLEND_COLOR_DWORD_COUNT_PLB	2
+
+typedef struct _state3d_coord_set_bindings_plb {
+	union {
+		struct {
+			unsigned int internal_tc_set_0_src :3;
+			unsigned int internal_tc_set_1_src :3;
+			unsigned int internal_tc_set_2_src :3;
+			unsigned int internal_tc_set_3_src :3;
+			unsigned int internal_tc_set_4_src :3;
+			unsigned int internal_tc_set_5_src :3;
+			unsigned int internal_tc_set_6_src :3;
+			unsigned int internal_tc_set_7_src :3;
+			unsigned int :8;
+		};
+		unsigned int dw0;
+	};
+	unsigned int updated;
+} state3d_coord_set_bindings_plb_t;
+#define STATE3D_COORD_SET_BINDINGS_UPDATED_PLB		1
+#define STATE3D_COORD_SET_BINDINGS_DWORD_COUNT_PLB	1
+
+typedef struct _state3d_default_diffuse_plb {
+	union {
+		unsigned int color;
+		unsigned int dw1;
+	};
+	unsigned int updated;
+} state3d_default_diffuse_plb_t;
+#define STATE3D_DEFAULT_DIFFUSE_UPDATED_PLB		1
+#define STATE3D_DEFAULT_DIFFUSE_DWORD_COUNT_PLB		2
+
+typedef struct _state3d_default_specular_plb {
+	union {
+		unsigned int color;
+		unsigned int dw1;
+	};
+	unsigned int updated;
+} state3d_default_specular_plb_t;
+#define STATE3D_DEFAULT_SPECULAR_UPDATED_PLB		1
+#define STATE3D_DEFAULT_SPECULAR_DWORD_COUNT_PLB	2
+
+typedef struct _state3d_default_z_plb {
+	union {
+		unsigned int depth;
+		unsigned int dw1;
+	};
+	unsigned int updated;
+} state3d_default_z_plb_t;
+#define STATE3D_DEFAULT_Z_UPDATED_PLB			1
+#define STATE3D_DEFAULT_Z_DWORD_COUNT_PLB		2
+
+typedef struct _state3d_depth_offset_scale_plb {
+	union {
+		unsigned int global_val;
+		unsigned int dw1;
+	};
+	unsigned int updated;
+} state3d_depth_offset_scale_plb_t;
+#define STATE3D_DEPTH_OFFSET_SCALE_UPDATED_PLB		1
+#define STATE3D_DEPTH_OFFSET_SCALE_DWORD_COUNT_PLB	2
+
+typedef struct _state3d_depth_subrectangle_enable_plb {
+	union {
+		struct {
+			unsigned int enable :1;	/* B-spec says this is difeatured, MUST BE DISABLE */
+			unsigned int mod_en :1;
+			unsigned int :30;
+		};
+		unsigned int dw0;
+	};
+	unsigned int updated;
+} state3d_depth_subrectangle_enable_plb_t;
+#define STATE3D_DEPTH_SUBRECTANGLE_ENABLE_UPDATED_PLB		1
+#define STATE3D_DEPTH_SUBRECTANGLE_ENABLE_DWORD_COUNT_PLB	1
+
+typedef struct _state3d_dest_buffer_variables_plb {
+	union {
+		struct {
+			unsigned int vert_line_stride_offset :1;
+			unsigned int vert_line_stride :1;
+			unsigned int depth_buffer_format :2;
+			unsigned int :4;
+			unsigned int color_buffer_format :4;
+			unsigned int write_select_422_channel :3;
+			unsigned int :1;
+			unsigned int dest_origin_vert_bias :4;
+			unsigned int dest_origin_horiz_bias :4;
+			unsigned int dither_enhance_dis :1;
+			unsigned int linear_gamma_blend_en :1;
+			unsigned int dither_pattern_select :2;
+			unsigned int lod_preclamp_en :1;
+			unsigned int early_depth_test_en :1;
+			unsigned int texture_default_color_mode :1;
+			unsigned int :1;
+		};
+		unsigned int dw1;
+	};
+	unsigned int updated;
+} state3d_dest_buffer_variables_plb_t;
+#define STATE3D_DEST_BUFFER_VARIABLES_UPDATED_PLB	      1
+#define STATE3D_DEST_BUFFER_VARIABLES_DWORD_COUNT_PLB	  2
+
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_8BIT          0
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_X1R5G6B5      1
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_R5G6B5        2
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_A8R8G8B8      3
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_YCRCB_SWAPY   4
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_YCRCB_NORMAL  5
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_YCRCB_SWAPUV  6
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_YCRCB_SWAPUVY 7
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_A4R4G4B4      8
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_A1R5G5B5      9
+#define STATE3D_DEST_BUFF_COLOR_BUFF_FORMAT_A2R10G10B10   0xA
+
+typedef struct _state3d_drawing_rectangle_plb {
+	union {
+		struct {
+			unsigned int :24;
+		unsigned int y_dither_offset :2;
+		unsigned int x_dither_offset :2;
+			unsigned int :2;
+		unsigned int depth_buffer_coord_offset_dis :1;
+		unsigned int fast_scissor_clip_dis :1;
+		};
+		unsigned int dw1;
+	};
+	union {
+		struct {
+		unsigned int clip_draw_rect_x_min :16;
+		unsigned int clip_draw_rect_y_min :16;
+		};
+		unsigned int dw2;
+	};
+	union {
+		struct {
+		unsigned int clip_draw_rect_x_max :16;
+		unsigned int clip_draw_rect_y_max :16;
+		};
+		unsigned int dw3;
+	};
+	union {
+		struct {
+		unsigned int draw_rect_origin_x :16;
+		unsigned int draw_rect_origin_y :16;
+		};
+		unsigned int dw4;
+	};
+	unsigned int updated;
+} state3d_drawing_rectangle_plb_t;
+#define STATE3D_DRAWING_RECTANGLE_UPDATED_PLB		1
+#define STATE3D_DRAWING_RECTANGLE_DWORD_COUNT_PLB	5
+
+typedef struct _state3d_filter_coefficients_4x4_plb {
+	/* FIXME: This might be an over simplified abstraction
+	 * and may subject to change to meet its semantic later */
+	unsigned int filter1[32];
+	unsigned int filter2[32];
+	unsigned int updated;
+} state3d_filter_coefficients_4x4_plb_t;
+#define STATE3D_FILTER_COEFFICIENT_4X4_UPDATED_PLB	1
+#define STATE3D_FILTER_COEFFICIENT_4X4_DWORD_COUNT_PLB	65
+
+typedef struct _state3d_filter_coefficients_6x5_plb {
+	union {
+		struct {
+			unsigned int k1 :16;
+			unsigned int k2 :16;
+		};
+		unsigned int dw1;
+	};
+	union {
+		struct {
+			unsigned int k3 :16;
+			unsigned int k4 :16;
+		};
+		unsigned int dw2;
+	};
+	union {
+		struct {
+			unsigned int k5 :16;
+			unsigned int k6 :16;
+		};
+		unsigned int dw3;
+	};
+	unsigned int updated;
+} state3d_filter_coefficients_6x5_plb_t;
+#define STATE3D_FILTER_COEFFICIENT_6X5_UPDATED_PLB	1
+#define STATE3D_FILTER_COEFFICIENT_6X5_DWORD_COUNT_PLB	4
+
+typedef struct _state3d_fog_color_plb {
+	union {
+		struct {
+			unsigned int blue :8;
+			unsigned int green :8;
+			unsigned int red :8;
+			unsigned int :8;
+		};
+		unsigned int dw0;
+	};
+	unsigned int updated;
+} state3d_fog_color_plb_t;
+#define STATE3D_FOG_COLOR_UPDATED_PLB		1
+#define STATE3D_FOG_COLOR_DWORD_COUNT_PLB	1
+
+typedef struct _state3d_fog_mode_plb {
+	union {
+		struct {
+			unsigned int :4;
+			unsigned int linear_fog_c1_const:16;
+			unsigned int :3;
+			unsigned int fog_density_mod_en: 1;
+			unsigned int linear_fog_c1c2_const_mod_en :1;
+			unsigned int fog_source :1;
+			unsigned int :1;
+			unsigned int fog_source_mod_en :1;
+			unsigned int fog_func :2;
+			unsigned int :1;
+			unsigned int fog_func_mod_en :1;
+		};
+		unsigned int dw1;
+	};
+	union {
+		unsigned int linear_fog_c2_const;
+		unsigned int dw2;
+	};
+	union {
+		unsigned int fog_density;
+		unsigned int dw3;
+	};
+	unsigned int updated;
+} state3d_fog_mode_plb_t;
+
+#define STATE3D_FOG_MODE_UPDATED_PLB		1
+#define STATE3D_FOG_MODE_DWORD_COUNT_PLB	4
+
+typedef struct _state3d_independent_alpha_blend_plb {
+	union {
+		struct {
+			unsigned int dest_factor :4;
+			unsigned int :1;
+			unsigned int dest_factor_mod_en :1;
+			unsigned int src_factor :4;
+			unsigned int :1;
+			unsigned int src_factor_mod_en :1;
+			unsigned int :4;
+			unsigned int function :3;
+			unsigned int :2;
+			unsigned int function_mod_en :1;
+			unsigned int enable :1;
+			unsigned int enable_mod_en :1;
+			unsigned int :8;
+		};
+		unsigned int dw0;
+	};
+	unsigned int updated;
+} state3d_independent_alpha_blend_plb_t;
+#define STATE3D_INDEPENDENT_ALPHA_BLEND_UPDATED_PLB	1
+#define STATE3D_INDEPENDENT_ALPHA_BLEND_DWORD_COUNT_PLB	1
+
+typedef struct _state3d_load_indirect_plb {
+	union {
+		struct {
+			unsigned int block_num :8;
+			unsigned int block_mask :6;
+			unsigned int mem_space_select :1;
+			unsigned int :17;
+		};
+		unsigned int dw0;
+	};
+	union {
+		struct {
+			unsigned int static_buffer_valid :1;
+			unsigned int force_static_load :1;
+			unsigned int static_buffer_addr :30;
+		};
+		unsigned int dw_sis0;
+	};
+	union {
+		struct {
+			unsigned int static_buffer_length :9;
+			unsigned int :23;
+		};
+		unsigned int dw_sis1;
+	};
+	union {
+		struct {
+			unsigned int dynamic_buffer_valid :1;
+			unsigned int dynamic_buffer_reset :1;
+			unsigned int dynamic_buffer_addr :30;
+		};
+		unsigned int dw_dis0;
+	};
+	union {
+		struct {
+			unsigned int sampler_buffer_valid :1;
+			unsigned int force_sampler_load :1;
+			unsigned int sampler_buffer_addr :30;
+		};
+		unsigned int dw_ssb0;
+	};
+	union {
+		struct {
+			unsigned int sampler_buffer_length :9;
+			unsigned int :23;
+		};
+		unsigned int dw_ssb1;
+	};
+	union {
+		struct {
+			unsigned int map_buffer_valid :1;
+			unsigned int force_map_load :1;
+			unsigned int map_buffer_addr :30;
+		};
+		unsigned int dw_msb0;
+	};
+	union {
+		struct {
+			unsigned int map_buffer_length :9;
+			unsigned int :23;
+		};
+		unsigned int dw_msb1;
+	};
+	union {
+		struct {
+			unsigned int psp_buffer_valid :1;
+			unsigned int force_psp_load :1;
+			unsigned int psp_buffer_addr :30;
+		};
+		unsigned int dw_psp0;
+	};
+	union {
+		struct {
+			unsigned int psp_buffer_length :9;
+			unsigned int :23;
+		};
+		unsigned int dw_psp1;
+	};
+	union {
+		struct {
+			unsigned int psc_buffer_valid :1;
+			unsigned int force_psc_load :1;
+			unsigned int psc_buffer_addr :30;
+		};
+		unsigned int dw_psc0;
+	};
+	union {
+		struct {
+			unsigned int psc_buffer_length :9;
+			unsigned int :23;
+		};
+		unsigned int dw_psc1;
+	};
+	unsigned int updated;
+} state3d_load_indirect_plb_t;
+#define STATE3D_LOAD_INDIRECT_UPDATED_PLB		1
+#define STATE3D_LOAD_INDIRECT_DWORD_COUNT_PLB		12
+#define STATE3D_LOAD_INDIRECT_HEADER_DWORD_COUNT_PLB	1
+#define STATE3D_LOAD_INDIRECT_PSP_DWORD_COUNT_PLB	2
+
+typedef struct _state3d_load_state_immediate_1_plb {
+	union {
+		struct {
+			unsigned int state_num :4;
+			unsigned int load_dw_s0 :1;
+			unsigned int load_dw_s1 :1;
+			unsigned int load_dw_s2 :1;
+			unsigned int load_dw_s3 :1;
+			unsigned int load_dw_s4 :1;
+			unsigned int load_dw_s5 :1;
+			unsigned int load_dw_s6 :1;
+			unsigned int load_dw_s7 :1;
+			unsigned int :20;
+		};
+		unsigned int dw0;
+	};
+	union {
+		struct {
+			unsigned int vtx_cache_invalid_dis :1;
+			unsigned int :1;
+			unsigned int vtx_buf_addr :26;
+			unsigned int :4;
+		};
+		unsigned int dw_s0;
+	};
+	union {
+		struct {
+			unsigned int :16;
+			unsigned int vtx_buf_pitch :6;
+			unsigned int :2;
+			unsigned int vtx_buf_width :6;
+			unsigned int :2;
+		};
+		unsigned int dw_s1;
+	};
+	union {
+		/*
+		struct {
+			unsigned int :4;
+		} tex_coord_set_fmt[8];
+		*/
+		struct {
+			unsigned int tex_coord_set_0_fmt :4;
+			unsigned int tex_coord_set_1_fmt :4;
+			unsigned int tex_coord_set_2_fmt :4;
+			unsigned int tex_coord_set_3_fmt :4;
+			unsigned int tex_coord_set_4_fmt :4;
+			unsigned int tex_coord_set_5_fmt :4;
+			unsigned int tex_coord_set_6_fmt :4;
+			unsigned int tex_coord_set_7_fmt :4;
+		};
+		unsigned int dw_s2;
+	};
+	union {
+		/*
+		struct {
+			unsigned int pspec_crtn_dis :1;
+			unsigned int wrap_short_tcz :1;
+			unsigned int wrap_short_tcy :1;
+			unsigned int wrap_short_tcx :1;
+		} tex_coor_set[8];
+		*/
+		struct {
+			unsigned int tex_coord_set_0_pspec_crtn_dis :1;
+			unsigned int tex_coord_set_0_wrap_short_tcz :1;
+			unsigned int tex_coord_set_0_wrap_short_tcy :1;
+			unsigned int tex_coord_set_0_wrap_short_tcx :1;
+
+			unsigned int tex_coord_set_1_pspec_crtn_dis :1;
+			unsigned int tex_coord_set_1_wrap_short_tcz :1;
+			unsigned int tex_coord_set_1_wrap_short_tcy :1;
+			unsigned int tex_coord_set_1_wrap_short_tcx :1;
+
+			unsigned int tex_coord_set_2_pspec_crtn_dis :1;
+			unsigned int tex_coord_set_2_wrap_short_tcz :1;
+			unsigned int tex_coord_set_2_wrap_short_tcy :1;
+			unsigned int tex_coord_set_2_wrap_short_tcx :1;
+
+			unsigned int tex_coord_set_3_pspec_crtn_dis :1;
+			unsigned int tex_coord_set_3_wrap_short_tcz :1;
+			unsigned int tex_coord_set_3_wrap_short_tcy :1;
+			unsigned int tex_coord_set_3_wrap_short_tcx :1;
+
+			unsigned int tex_coord_set_4_pspec_crtn_dis :1;
+			unsigned int tex_coord_set_4_wrap_short_tcz :1;
+			unsigned int tex_coord_set_4_wrap_short_tcy :1;
+			unsigned int tex_coord_set_4_wrap_short_tcx :1;
+
+			unsigned int tex_coord_set_5_pspec_crtn_dis :1;
+			unsigned int tex_coord_set_5_wrap_short_tcz :1;
+			unsigned int tex_coord_set_5_wrap_short_tcy :1;
+			unsigned int tex_coord_set_5_wrap_short_tcx :1;
+
+			unsigned int tex_coord_set_6_pspec_crtn_dis :1;
+			unsigned int tex_coord_set_6_wrap_short_tcz :1;
+			unsigned int tex_coord_set_6_wrap_short_tcy :1;
+			unsigned int tex_coord_set_6_wrap_short_tcx :1;
+
+			unsigned int tex_coord_set_7_pspec_crtn_dis :1;
+			unsigned int tex_coord_set_7_wrap_short_tcz :1;
+			unsigned int tex_coord_set_7_wrap_short_tcy :1;
+			unsigned int tex_coord_set_7_wrap_short_tcx :1;
+
+		};
+		unsigned int dw_s3;
+	};
+	union {
+		struct {
+			unsigned int anti_alias_en :1;
+			unsigned int sprite_point_en :1;
+			unsigned int fog_param_present :1;
+			unsigned int local_depth_offset_en :1;
+			unsigned int force_specular_diffuse_color :1;
+			unsigned int force_default_diffuse_color :1;
+			unsigned int position_mask :3;
+			unsigned int local_depth_offset_present: 1;
+			unsigned int diffuse_color_present :1;
+			unsigned int specular_color_fog_factor_present :1;
+			unsigned int point_width_present :1;
+			unsigned int cull_mode :2;
+			unsigned int color_shade_mode :1;
+			unsigned int specular_shade_mode :1;
+			unsigned int fog_shade_mode :1;
+			unsigned int alpha_shade_mode :1;
+			unsigned int line_width :4;
+			unsigned int point_width :9;
+		};
+		unsigned int dw_s4;
+	};
+	union {
+		struct {
+			unsigned int logic_op_en :1;
+			unsigned int color_dither_en :1;
+			unsigned int stencil_test_en :1;
+			unsigned int stencil_buffer_write_en :1;
+			unsigned int stencil_pass_depth_pass_op :3;
+			unsigned int stencil_pass_depth_fail_op :3;
+			unsigned int stencil_fail_op :3;
+			unsigned int stencil_test_func :3;
+			unsigned int stencil_ref_val :8;
+			unsigned int fog_enable :1;
+			unsigned int global_depth_offset_en :1;
+			unsigned int last_pixel_en :1;
+			unsigned int force_default_point_width :1;
+			unsigned int color_buffer_component_write_dis :4;
+		};
+		unsigned int dw_s5;
+	};
+	union {
+		struct {
+			unsigned int triang_list_provoke_vtx_sel :2;
+			unsigned int color_buffer_write_en :1;
+			unsigned int depth_buffer_write_en :1;
+			unsigned int dest_blend_factor :4;
+			unsigned int src_blend_factor :4;
+			unsigned int color_blend_func :3;
+			unsigned int color_buffer_blend_en :1;
+			unsigned int depth_test_func :3;
+			unsigned int depth_test_en :1;
+			unsigned int alpha_ref_val :8;
+			unsigned int alpha_test_func :3;
+			unsigned int alpha_test_en :1;
+		};
+		unsigned int dw_s6;
+	};
+	union {
+		unsigned int global_depth_offset_const;
+		unsigned int dw_s7;
+	};
+	unsigned int updated;
+} state3d_load_state_immediate_1_plb_t;
+/* FIXME: Need to refine to smaller enable flags */
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_UPDATED_PLB			1
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_HEADER_DWORD_COUNT_PLB		1
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_STATES_ALL_DWORD_COUNT_PLB	8
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_BLENDFACTOR_ZERO			1
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_BLENDFACTOR_ONE			2
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_BLENDFACTOR_SRC_ALPHA		5
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_BLENDFACTOR_INV_SRC_ALPHA	6
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_BLENDFACTOR_DST_ALPHA		7
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_BLENDFACTOR_INV_DST_ALPHA	8
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_BLENDFACTOR_CONST_ALPHA		0xe
+#define STATE3D_LOAD_STATE_IMMEDIATE_1_BLENDFACTOR_INV_CONST_ALPHA	0xf
+
+typedef struct _state3d_map_deinterlacer_parameters_plb {
+	union {
+		struct {
+			unsigned int da_en_y :1;
+			unsigned int da_en_uv :1;
+			unsigned int :30;
+		};
+		unsigned int dw1;
+	};
+	union {
+		struct {
+			unsigned int edge_threshold_low_y :8;
+			unsigned int edge_threshold_high_y :8;
+			unsigned int edge_threshold_low_uv :8;
+			unsigned int edge_threshold_high_uv :8;
+		};
+		unsigned int dw2;
+	};
+	unsigned int updated;
+} state3d_map_deinterlacer_parameters_plb_t;
+#define STATE3D_MAP_DEINTERLACER_PARAMETERS_UPDATED_PLB		1
+#define STATE3D_MAP_DEINTERLACER_PARAMETERS_DWORD_COUNT_PLB	3
+
+typedef struct _state3d_map_palette_load_32_plb {
+	union {
+		struct {
+			unsigned int color_num :4;
+			unsigned int :12;
+			unsigned int :16;
+		};
+		unsigned int dw0;
+	};
+	unsigned int color[16];
+	unsigned int updated;
+} state3d_map_palette_load_32_plb_t;
+#define STATE3D_MAP_PALETTE_LOAD_32_UPDATED_PLB		1
+#define STATE3D_MAP_PALETTE_LOAD_32_DWORD_COUNT_PLB	17
+
+typedef	struct _state3d_map_state_texmap_plb {
+		union {
+			struct {
+				unsigned int vert_stride_offset :1;
+				unsigned int vert_stride :1;
+				unsigned int base_addr :26;
+				unsigned int :3;
+			};
+			unsigned int tm_dw0;
+		};
+		union {
+			struct {
+				unsigned int tile_walk :1;
+				unsigned int tiled_surface :1;
+				unsigned int util_fence_regs :1;
+				unsigned int texel_format :4;
+				unsigned int surface_format :3;
+				unsigned int width :11;
+				unsigned int height :11;
+			};
+			unsigned int tm_dw1;
+		};
+		union {
+			struct {
+				unsigned int depth :8;
+				unsigned int :1;
+				unsigned int max_lod :6;
+				unsigned int cube_face_en :6;
+				unsigned int dword_pitch :11;
+			};
+			unsigned int tm_dw2;
+		};
+} state3d_map_state_texmap_plb_t;
+#define STATE3D_MAP_STATE_MAPSURF_8BIT_PLB		1
+  #define STATE3D_MAP_STATE_MAPSURF_8BIT_MAPTEXEL_I8_PLB		0
+  #define STATE3D_MAP_STATE_MAPSURF_8BIT_MAPTEXEL_L8_PLB		1
+  #define STATE3D_MAP_STATE_MAPSURF_8BIT_MAPTEXEL_A4P4_PLB		2
+  #define STATE3D_MAP_STATE_MAPSURF_8BIT_MAPTEXEL_P4A4_PLB		3
+  #define STATE3D_MAP_STATE_MAPSURF_8BIT_MAPTEXEL_A8_PLB		4
+  #define STATE3D_MAP_STATE_MAPSURF_8BIT_MAPTEXEL_MONO8_PLB		5
+#define STATE3D_MAP_STATE_MAPSURF_16BIT_PLB		2
+  #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_R5G6B5_PLB		0
+  #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_A1R5G5B5_PLB		1
+  #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_A4R4G4B4_PLB		2
+  #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_A8L8_PLB		3
+  #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_V8U8_PLB		5
+  #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_L6V5U5_PLB		6
+  #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_I16_PLB		7
+  #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_L16_PLB		8
+  #define STATE3D_MAP_STATE_MAPSURF_16BIT_MAPTEXEL_A16_PLB		9
+#define STATE3D_MAP_STATE_MAPSURF_32BIT_PLB		3
+  #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_A8R8G8B8_PLB		0
+  #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_A8B8G8R8_PLB		1
+  #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_X8R8G8B8_PLB		2
+  #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_X8B8G8R8_PLB		3
+  #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_Q8W8V8U8_PLB		4
+  #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_A8X8V8U8_PLB		5
+  #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_L8X8V8U8_PLB		6
+  #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_X8L8V8U8_PLB		7
+  #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_A2R10G10B10_PLB	8
+  #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_A2B10G10R10_PLB	9
+  #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_A2W10V10U10_PLB	0xA
+  #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_G16R16_PLB		0xB
+  #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_V16U16_PLB		0xC
+  #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_X8I24_PLB		0xD
+  #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_X8L24_PLB		0xE
+  #define STATE3D_MAP_STATE_MAPSURF_32BIT_MAPTEXEL_X8A24_PLB		0xF
+  #define STATE3D_MAP_STATE_MAPSURF_422_PLB		5
+  #define STATE3D_MAP_STATE_MAPSURF_422_MAPTEXEL_YCRCB_SWAPY_PLB	0
+  #define STATE3D_MAP_STATE_MAPSURF_422_MAPTEXEL_YCRCB_NORMAL_PLB	1
+  #define STATE3D_MAP_STATE_MAPSURF_422_MAPTEXEL_YCRCB_SWAPUV_PLB	2
+  #define STATE3D_MAP_STATE_MAPSURF_422_MAPTEXEL_YCRCB_SWAPUVY_PLB	3
+  #define STATE3D_MAP_STATE_MAPSURF_COMPRESSED_PLB	6
+  #define STATE3D_MAP_STATE_MAPSURF_COMPRESSED_MAPTEXEL_DX1_PLB		0
+  #define STATE3D_MAP_STATE_MAPSURF_COMPRESSED_MAPTEXEL_DX2_3_PLB	1
+  #define STATE3D_MAP_STATE_MAPSURF_COMPRESSED_MAPTEXEL_DX4_5_PLB	2
+  #define STATE3D_MAP_STATE_MAPSURF_COMPRESSED_MAPTEXEL_FX1_PLB		3
+  #define STATE3D_MAP_STATE_MAPSURF_COMPRESSED_MAPTEXEL_DX1_RGB_PLB	4
+#define STATE3D_MAP_STATE_MAPSURF_4BIT_INDEXED_PLB	7
+  #define STATE3D_MAP_STATE_MAPSURF_4BIT_INDEXED_MAPTEXEL_A8R8G8B8_PLB	7
+typedef struct _state3d_map_state_plb {
+	union {
+		struct {
+			unsigned int map_num :6;
+			unsigned int :9;
+			unsigned int retain :1;
+			unsigned int :16;
+		};
+		unsigned int dw0;
+	};
+	union {
+		struct {
+			unsigned int map_mask :16;
+			unsigned int :16;
+		};
+		unsigned int dw1;
+	};
+	state3d_map_state_texmap_plb_t texmap[16]; /* Napa support 16 texture maps, B-spec-1a pg198 */
+	unsigned int updated;
+} state3d_map_state_plb_t;
+/* FIXME: Need to refine to smaller enable flags */
+#define STATE3D_MAP_STATE_UPDATED_PLB			1
+#define STATE3D_MAP_STATE_MAX_DWORD_COUNT_PLB		50
+#define STATE3D_MAP_STATE_HEADER_DWORD_COUNT_PLB	2
+#define STATE3D_MAP_STATE_SINGLE_TM_DWORD_COUNT_PLB	3
+
+typedef struct _state3d_modes_4_plb {
+	union {
+		struct {
+			unsigned int stencil_write_mask :8;
+			unsigned int stencil_test_mask :8;
+			unsigned int stencil_write_mask_mod_en :1;
+			unsigned int stencil_test_mask_mod_en :1;
+			unsigned int logic_op_func :4;
+			unsigned int :1;
+			unsigned int logic_op_func_mod_en :1;
+			unsigned int :8;
+		};
+		unsigned int dw0;
+	};
+	unsigned int updated;
+} state3d_modes_4_plb_t;
+#define STATE3D_MODES_4_UPDATED_PLB		1
+#define STATE3D_MODES_4_DWORD_COUNT_PLB		1
+
+typedef struct _state3d_modes_5_plb {
+	union {
+		struct {
+			unsigned int :16;
+			unsigned int pipelined_tex_cache_op :1;
+			unsigned int tex_cache_dis :1;
+			unsigned int pipelined_render_cache_op :1;
+			unsigned int :13;
+		};
+		unsigned int dw0;
+	};
+	unsigned int updated;
+} state3d_modes_5_plb_t;
+
+#define STATE3D_MODES_5_UPDATED_PLB		1
+#define STATE3D_MODES_5_DWORD_COUNT_PLB		1
+
+typedef struct _state3d_pixel_shader_const_elem_plb {
+	unsigned int const_x;
+	unsigned int const_y;
+	unsigned int const_z;
+	unsigned int const_w;
+} state3d_pixel_shader_const_elem_plb_t;
+
+typedef struct _state3d_pixel_shader_constants_plb {
+	union {
+		struct {
+			unsigned int const_num :8;
+			unsigned int :24;
+		};
+		unsigned int dw0;
+	};
+	union {
+		unsigned int reg_mask;
+		unsigned int dw1;
+	};
+	state3d_pixel_shader_const_elem_plb_t elem[32];
+	unsigned int updated;
+} state3d_pixel_shader_constants_plb_t;
+#define STATE3D_PIXEL_SHADER_CONSTANTS_UPDATED_PLB		1
+#define STATE3D_PIXEL_SHADER_CONSTANTS_HEADER_DWORD_COUNT_PLB	2
+#define STATE3D_PIXEL_SHADER_CONSTANTS_SINGLE_ELEM_DWORD_COUNT_PLB	4
+
+typedef struct _state3d_pixel_shader_program_ari_instr_plb {
+	union {
+		struct {
+			unsigned int :2;
+			unsigned int src0_reg_num :5;
+			unsigned int src0_reg_type :3;
+			unsigned int dest_channel_mask :4;
+			unsigned int dest_reg_num :4;
+			unsigned int :1;
+			unsigned int dest_reg_type :3;
+			unsigned int dest_saturate :1;
+			unsigned int :1;
+			unsigned int opcode :5;
+			unsigned int :3;
+		};
+		unsigned int dw0;
+	};
+	union {
+		struct {
+			unsigned int src1_y_channel_select :3;
+			unsigned int src1_y_channel_negate :1;
+			unsigned int src1_x_channel_select :3;
+			unsigned int src1_x_channel_negate :1;
+			unsigned int src1_reg_num :5;
+			unsigned int src1_reg_type :3;
+			unsigned int src0_w_channel_select :3;
+			unsigned int src0_w_channel_negate :1;
+			unsigned int src0_z_channel_select :3;
+			unsigned int src0_z_channel_negate :1;
+			unsigned int src0_y_channel_select :3;
+			unsigned int src0_y_channel_negate :1;
+			unsigned int src0_x_channel_select :3;
+			unsigned int src0_x_channel_negate :1;
+		};
+		unsigned int dw1;
+	};
+	union {
+		struct {
+			unsigned int src2_w_channel_select :3;
+			unsigned int src2_w_channel_negate :1;
+			unsigned int src2_z_channel_select :3;
+			unsigned int src2_z_channel_negate :1;
+			unsigned int src2_y_channel_select :3;
+			unsigned int src2_y_channel_negate :1;
+			unsigned int src2_x_channel_select :3;
+			unsigned int src2_x_channel_negate :1;
+			unsigned int src2_reg_num :5;
+			unsigned int src2_reg_type :3;
+			unsigned int src1_w_channel_select :3;
+			unsigned int src1_w_channel_negate :1;
+			unsigned int src1_z_channel_select :3;
+			unsigned int src1_z_channel_negate :1;
+		};
+		unsigned int dw2;
+	};
+
+	void * next_instr;
+	unsigned char ps_id;
+} state3d_pixel_shader_program_ari_instr_plb_t;
+
+typedef struct _state3d_pixel_shader_program_tex_instr_plb {
+	union {
+		struct {
+			unsigned int samp_reg_num :4;
+			unsigned int :10;
+			unsigned int dest_reg_num :4;
+			unsigned int :1;
+			unsigned int dest_reg_type :3;
+			unsigned int :2;
+			unsigned int opcode :5;
+			unsigned int :3;
+		};
+		unsigned int dw0;
+	};
+	union {
+		struct {
+			unsigned int :17;
+			unsigned int addr_reg_num :4;
+			unsigned int :3;
+			unsigned int addr_reg_type :3;
+			unsigned int :5;
+		};
+		unsigned int dw1;
+	};
+	unsigned int dw2;
+
+	void * next_instr;
+	unsigned char ps_id;
+} state3d_pixel_shader_program_tex_instr_plb_t;
+
+typedef struct _state3d_pixel_shader_program_dcl_instr_plb {
+	union {
+		struct {
+			unsigned int :10;
+			unsigned int dcl_channel_mask :4;
+			unsigned int dcl_reg_num :4;
+			unsigned int :1;
+			unsigned int dcl_reg_type :2;
+			unsigned int :1;
+			unsigned int samp_type :2;
+			unsigned int opcode :5;
+			unsigned int :3;
+		};
+		unsigned int dw0;
+	};
+	unsigned int dw1;
+	unsigned int dw2;
+
+	void * next_instr;
+	unsigned char ps_id;
+} state3d_pixel_shader_program_dcl_instr_plb_t;
+
+typedef struct _state3d_pixel_shader_program_instr_plb {
+	unsigned int idw0;	//instruction's first dword
+	unsigned int idw1;	//instruction's second dword
+	unsigned int idw2;	//instruction's third dword
+} state3d_pixel_shader_program_instr_plb_t;
+
+typedef struct _state3d_pixel_shader_program_plb {
+	union {
+		struct {
+			unsigned int instr_num :9;
+			unsigned int :6;
+			unsigned int retain :1;
+			unsigned int :16;
+		};
+		unsigned int dw0;
+	};
+	state3d_pixel_shader_program_instr_plb_t instr[123];
+	unsigned int updated;
+} state3d_pixel_shader_program_plb_t;
+
+/*
+#define STATE3D_PIXEL_SHADER_PROGRAM_ARI_INSTR_UPDATED_PLB	1
+#define STATE3D_PIXEL_SHADER_PROGRAM_TEX_INSTR_UPDATED_PLB	1
+#define STATE3D_PIXEL_SHADER_PROGRAM_DCL_INSTR_UPDATED_PLB	1
+*/
+#define STATE3D_PIXEL_SHADER_PROGRAM_HEADER_DWORD_COUNT_PLB	1
+
+typedef struct _state3d_rasterization_rules_plb {
+	union {
+		struct {
+			unsigned int :3;
+			unsigned int tri_fan_provok_vtx_sel :2;
+			unsigned int tri_fan_provok_vtx_sel_mod_en :1;
+			unsigned int line_list_provok_vtx_sel :2;
+			unsigned int line_list_provok_vtx_sel_mod_en :1;
+			unsigned int texkill_3d4d :1;
+			unsigned int texkill_3d4d_mod_en :1;
+			unsigned int :1;
+			unsigned int snake_walk_dis :1;
+			unsigned int point_raster_rule :2;
+			unsigned int point_raster_rule_mod_en :1;
+			unsigned int zero_pixel_tri_filter_dis :1;
+			unsigned int zero_pixel_tri_filter_dis_mod_en :1;
+			unsigned int tri_2x2_filter_dis :1;
+			unsigned int tri_2x2_filter_dis_mod_en :1;
+			unsigned int :12;
+		};
+		unsigned int dw0;
+	};
+	unsigned int updated;
+} state3d_rasterization_rules_plb_t;
+#define STATE3D_RASTERIZATION_RULES_UPDATED_PLB		1
+#define STATE3D_RASTERIZATION_RULES_DWORD_COUNT_PLB	1
+
+typedef struct _state3d_sampler_state_samp_plb {
+	union {
+		struct {
+			unsigned int shadow_func :3;
+			unsigned int max_anisotropy :1;
+			unsigned int shadow_en :1;
+			unsigned int tex_lod_bias :9;
+			unsigned int min_mode_filter :3;
+			unsigned int mag_mode_filter :3;
+			unsigned int mip_mode_filter :2;
+			unsigned int base_mip_level :5;
+			unsigned int chroma_index :2;
+			unsigned int color_space_conv_en :1;
+			unsigned int planar_to_packed_en :1;
+			unsigned int reverse_gamma_en :1;
+		};
+		unsigned int ts_dw0;
+	};
+	union {
+		struct {
+			unsigned int east_deinterlace_en:1;
+			unsigned int map_index:4;
+			unsigned int normalized_coord:1;
+			unsigned int tcz_addr_ctrl_mode:3;
+			unsigned int tcy_addr_ctrl_mode:3;
+			unsigned int tcx_addr_ctrl_mode:3;
+			unsigned int chroma_en:1;
+			unsigned int keyed_tex_filter_mode:1;
+			unsigned int kill_pixel_en:1;
+			unsigned int :6;
+			unsigned int min_lod:8;
+		};
+		unsigned int ts_dw1;
+	};
+	union {
+		unsigned int default_color;
+		unsigned int ts_dw2;
+	};
+} state3d_sampler_state_samp_plb_t;
+
+typedef struct _state3d_sampler_state_plb {
+	union {
+		struct {
+			unsigned int samp_num :6;
+			unsigned int :26;
+		};
+		unsigned int dw0;
+	};
+	union {
+		struct {
+			unsigned int samp_mask :16;
+			unsigned int :16;
+		};
+		unsigned int dw1;
+	};
+	state3d_sampler_state_samp_plb_t samp[16]; /* Napa support up to 16 sampler */
+	unsigned int updated;
+} state3d_sampler_state_plb_t;
+/* FIXME: Need to refine smaller enable flags */
+#define STATE3D_SAMPLER_STATE_UPDATED_PLB			1
+#define STATE3D_SAMPLER_STATE_MAX_DWORD_COUNT_PLB		50
+#define STATE3D_SAMPLER_STATE_HEADER_DWORD_COUNT_PLB		2
+#define STATE3D_SAMPLER_STATE_SINGLE_TS_DWORD_COUNT_PLB		3
+
+typedef struct _state3d_scissor_enable_plb {
+	union {
+		struct {
+			unsigned int enable :1;
+			unsigned int enable_mod_en :1;
+			unsigned int :30;
+		};
+		unsigned int dw0;
+	};
+	unsigned int updated;
+} state3d_scissor_enable_plb_t;
+#define STATE3D_SCISSOR_ENABLE_UPDATED_PLB	1
+#define STATE3D_SCISSOR_ENABLE_DWORD_COUNT_PLB	1
+
+typedef struct _state3d_scissor_rectangle_plb {
+	union {
+		struct {
+			unsigned int x_min :16;
+			unsigned int y_min :16;
+		};
+		unsigned int dw1;
+	};
+	union {
+		struct {
+			unsigned int x_max :16;
+			unsigned int y_max :16;
+		};
+		unsigned int dw2;
+	};
+	unsigned int updated;
+
+} state3d_scissor_rectangle_plb_t;
+#define STATE3D_SCISSOR_RECTANGLE_UPDATED_PLB		1
+#define STATE3D_SCISSOR_RECTANGLE_DWORD_COUNT_PLB	3
+
+typedef struct _state3d_span_stipple_plb {
+	union {
+		struct {
+			unsigned int pattern :16;
+			unsigned int enable :1;
+			unsigned int :15;
+		};
+		unsigned int dw1;
+	};
+	unsigned int updated;
+} state3d_span_stipple_plb_t;
+#define STATE3D_SPAN_STIPPLE_UPDATED_PLB	1
+#define STATE3D_SPAN_STIPPLE_DWORD_COUNT_PLB	2
+
+#define COLOR_BUFFER_INDEX	0
+#define DEPTH_BUFFER_INDEX	1
+#define AUX0_BUFFER_INDEX	2
+#define AUX1_BUFFER_INDEX	3
+#define INTRA_BUFFER_INDEX	4
+
+#define ZONE_INIT_CLEARPARAM_INDEX  0
+#define CLEAR_RECT_CLEARPARAM_INDEX 1
+
+typedef struct _state3d_plb {
+	igd_surface_t					color_buffer;
+	igd_surface_t					depth_buffer;
+	state3d_anti_aliasing_plb_t 			anti_alias;
+	state3d_backface_stencil_ops_plb_t 		bface_stencil_ops;
+	state3d_backface_stencil_masks_plb_t 		bface_stencil_masks;
+	state3d_bin_control_plb_t 			bin_control;
+/*
+	state3d_buffer_info_plb_t 			dest_buffer_info;
+	state3d_buffer_info_plb_t 			depth_buffer_info;
+*/
+	state3d_buffer_info_plb_t			buffer_info[5];
+	state3d_chroma_key_plb_t 			chroma_key[4];
+	state3d_clear_parameters_plb_t 			clear_param[2];
+	state3d_constant_blend_color_plb_t 		const_blend_color;
+	state3d_coord_set_bindings_plb_t 		coord_set_bind;
+	state3d_default_diffuse_plb_t 			default_diffuse;
+	state3d_default_specular_plb_t 			default_specular;
+	state3d_default_z_plb_t 			default_z;
+	state3d_depth_offset_scale_plb_t 		depth_offset_scale;
+	state3d_depth_subrectangle_enable_plb_t 	depth_subrect_en;
+	state3d_dest_buffer_variables_plb_t		dest_buf_vars;
+	state3d_drawing_rectangle_plb_t			draw_rect;
+	state3d_filter_coefficients_4x4_plb_t		filter_coef_4x4;
+	state3d_filter_coefficients_6x5_plb_t		filter_coef_6x5;
+	state3d_fog_color_plb_t				fog_color;
+	state3d_fog_mode_plb_t				fog_mode;
+	state3d_independent_alpha_blend_plb_t		indep_alpha_blend;
+	state3d_load_indirect_plb_t			load_indirect;
+	state3d_load_state_immediate_1_plb_t		lsi1;
+	state3d_map_deinterlacer_parameters_plb_t	map_deinterlace_param;
+	state3d_map_palette_load_32_plb_t		map_pal_load_32;
+	state3d_map_state_plb_t				map_state;
+	state3d_modes_4_plb_t				modes_4;
+	state3d_modes_5_plb_t				modes_5;
+	state3d_pixel_shader_constants_plb_t		pixel_shader_const;
+	state3d_pixel_shader_program_plb_t		pixel_shader_program;
+/*	state3d_pixel_shader_program_dcl_instr_plb_t	pixel_shader_dcl;
+	state3d_pixel_shader_program_ari_instr_plb_t	pixel_shader_ari;
+	state3d_pixel_shader_program_tex_instr_plb_t	pixel_shader_tex;*/
+	state3d_rasterization_rules_plb_t		raster_rules;
+	state3d_sampler_state_plb_t			sampler_state;
+	state3d_scissor_enable_plb_t			scissor_en;
+	state3d_scissor_rectangle_plb_t			scissor_rect;
+	state3d_span_stipple_plb_t			span_stipple;
+} state3d_plb_t;
+
+int state3d_update_plb(igd_command_t ** in, state3d_plb_t *state, int load_all);
+int state3d_update_size_plb(state3d_plb_t *state);
+
+#define STATE3D_PLB(ac) ((state3d_plb_t*)((appcontext_plb_t*)ac)->state3d)
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/psb_regs.h b/drivers/gpu/drm/emgd/emgd/include/psb_regs.h
new file mode 100644
index 0000000..01edb09
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/psb_regs.h
@@ -0,0 +1,658 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: psb_regs.h
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the register definition file for the SGX and MSVDX cores.
+ *  These registers were formerly part of the plb/regs.h. They are taken out
+ *  because Atom E6xx shares the same core as PLB. This file is included in tnc/regs.h
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PSB_REGS_H_
+#define _PSB_REGS_H_
+
+extern unsigned long _sgx_base;
+/*-----------------------------------------------------------------------------
+ * SGX and MSVDX registers
+ ----------------------------------------------------------------------------*/
+#define SGX_BASE _sgx_base
+
+/* bits in PSB_EUR_CR_EVENT_STATUS */
+#define PSB_DPM_3D_MEM_FREE    (1<<0)
+#define PSB_OUT_OF_MEM_MT      (1<<1)
+#define PSB_OUT_OF_MEM_GBL     (1<<2)
+#define PSB_REACHED_MEM_THRESH (1<<3)
+#define PSB_TA_TERMINATE       (1<<12)
+#define PSB_TA_FINISHED        (1<<13)
+#define PSB_PIXELBE_END_RENDER (1<<18)
+#define PSB_DPM_TA_MEM_FREE    (1<<24)
+#define PSB_DPM_OUT_OF_MEM_ZLS (1<<25)
+#define PSB_TWOD_COMPLETE      (1<<27)
+#define PSB_TA_DPM_FAULT       (1<<28)
+
+/* PSB Registers */
+#define PSB_SGX_2D_CMD_SLAVE_PORT               (SGX_BASE + 0x4000)
+
+/* 0x000-0x0ff */
+/* CORE CLOCK GATING register definitions */
+#define PSB_CR_CLKGATECTL                       (SGX_BASE + 0x0000)
+#define _PSB_C_CLKGATECTL_CLKG_ENABLED          0x0
+#define _PSB_C_CLKGATECTL_CLKG_DISABLED         0x1
+#define _PSB_C_CLKGATECTL_CLKG_AUTO             0x2
+
+#define _PSB_C_CLKGATECTL_USE_CLKG_SHIFT        (20)
+#define _PSB_C_CLKGATECTL_DPM_CLKG_SHIFT        (16)
+#define _PSB_C_CLKGATECTL_TA_CLKG_SHIFT         (12)
+#define _PSB_C_CLKGATECTL_TSP_CLKG_SHIFT        (8)
+#define _PSB_C_CLKGATECTL_ISP_CLKG_SHIFT        (4)
+#define _PSB_C_CLKGATECTL_2D_CLKG_SHIFT         (0)
+
+#define _PSB_C_CLKGATECTL_USE_CLKG_MASK         (0x3 << 20)
+#define _PSB_C_CLKGATECTL_DPM_CLKG_MASK         (0x3 << 16)
+#define _PSB_C_CLKGATECTL_TA_CLKG_MASK          (0x3 << 12)
+#define _PSB_C_CLKGATECTL_TSP_CLKG_MASK         (0x3 << 8)
+#define _PSB_C_CLKGATECTL_ISP_CLKG_MASK         (0x3 << 4)
+#define _PSB_C_CLKGATECTL_2D_CLKG_MASK          (0x3 << 0)
+
+#define PSB_CR_CORE_ID                          (SGX_BASE + 0x0010)
+#define _PSB_CC_ID_ID_SHIFT                     (16)
+#define _PSB_CC_ID_ID_MASK                      (0xFFFF << 16)
+#define _PSB_CC_ID_CONFIG_SHIFT                 (0)
+#define _PSB_CC_ID_CONFIG_MASK                  (0xFFFF << 0)
+
+#define PSB_CR_CORE_REVISION                    (SGX_BASE + 0x0014)
+#define _PSB_CC_REVISION_DESIGNER_SHIFT         (24)
+#define _PSB_CC_REVISION_DESIGNER_MASK          (0xFF << 24)
+#define _PSB_CC_REVISION_MAJOR_SHIFT            (16)
+#define _PSB_CC_REVISION_MAJOR_MASK             (0xFF << 16)
+#define _PSB_CC_REVISION_MINOR_SHIFT            (8)
+#define _PSB_CC_REVISION_MINOR_MASK             (0xFF << 8)
+#define _PSB_CC_REVISION_MAINTENANCE_SHIFT      (0)
+#define _PSB_CC_REVISION_MAINTENANCE_MASK       (0xFF << 0)
+
+#define PSB_CR_SOFT_RESET						(SGX_BASE + 0x0080)
+#define _PSB_CS_RESET_TSP_RESET					(1 << 6)
+#define _PSB_CS_RESET_ISP_RESET					(1 << 5)
+#define _PSB_CS_RESET_USE_RESET					(1 << 4)
+#define _PSB_CS_RESET_TA_RESET					(1 << 3)
+#define _PSB_CS_RESET_DPM_RESET					(1 << 2)
+#define _PSB_CS_RESET_TWOD_RESET				(1 << 1)
+#define _PSB_CS_RESET_BIF_RESET					(1 << 0)
+
+/* 0x100-0x200 */
+
+#define PSB_CR_EVENT_HOST_ENABLE2               (SGX_BASE + 0x0110)
+#define PSB_CR_EVENT_HOST_CLEAR2                (SGX_BASE + 0x0114)
+#define PSB_CR_EVENT_STATUS2                    (SGX_BASE + 0x0118)
+#define PSB_TRIG_TA                             (1 << 7)
+#define PSB_TRIG_3D                             (1 << 6)
+#define PSB_TRIG_DL                             (1 << 5)
+#define PSB_BIF_REQ_FAULT                       (1 << 4)
+#define _PSB_CE_BIF_REQUESTER_FAULT             (1 << 4)
+#define _PSB_CE_DPM_DHOST_FREE_LOAD             (1 << 3)
+#define _PSB_CE_DPM_HOST_FREE_LOAD              (1 << 2)
+#define _PSB_CE_DPM_3D_FREE_LOAD                (1 << 1)
+#define _PSB_CE_DPM_TA_FREE_LOAD                (1 << 0)
+
+#define PSB_EUR_CR_EVENT_STATUS                 (SGX_BASE + 0x012c)
+
+#define PSB_CR_EVENT_STATUS                     (SGX_BASE + 0x012C)
+
+#define PSB_EUR_CR_EVENT_HOST_ENABLE            (SGX_BASE + 0x0130)
+
+#define PSB_CR_EVENT_HOST_CLEAR                 (SGX_BASE + 0x0134)
+#define _PSB_CE_MASTER_INTERRUPT                (1 << 31)
+#define _PSB_CE_TIMER                           (1 << 29)
+#define _PSB_CE_TA_DPM_FAULT                    (1 << 28)
+#define _PSB_CE_TWOD_COMPLETE                   (1 << 27)
+#define _PSB_CE_MADD_CACHE_INVALCOMPLETE        (1 << 26)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_ZLS           (1 << 25)
+#define _PSB_CE_DPM_TA_MEM_FREE                 (1 << 24)
+#define _PSB_CE_ISP_END_TILE                    (1 << 23)
+#define _PSB_CE_DPM_INITEND                     (1 << 22)
+#define _PSB_CE_OTPM_LOADED                     (1 << 21)
+#define _PSB_CE_OTPM_INV                        (1 << 20)
+#define _PSB_CE_OTPM_FLUSHED                    (1 << 19)
+#define _PSB_CE_PIXELBE_END_RENDER              (1 << 18)
+#define _PSB_CE_ISP_HALT                        (1 << 17)
+#define _PSB_CE_ISP_VISIBILITY_FAIL             (1 << 16)
+#define _PSB_CE_BREAKPOINT                      (1 << 15)
+#define _PSB_CE_SW_EVENT                        (1 << 14)
+#define _PSB_CE_TA_FINISHED                     (1 << 13)
+#define _PSB_CE_TA_TERMINATE                    (1 << 12)
+#define _PSB_CE_TPC_CLEAR                       (1 << 11)
+#define _PSB_CE_TPC_FLUSH                       (1 << 10)
+#define _PSB_CE_DPM_CONTROL_CLEAR               (1 << 9)
+#define _PSB_CE_DPM_CONTROL_LOAD                (1 << 8)
+#define _PSB_CE_DPM_CONTROL_STORE               (1 << 7)
+#define _PSB_CE_DPM_STATE_CLEAR                 (1 << 6)
+#define _PSB_CE_DPM_STATE_LOAD                  (1 << 5)
+#define _PSB_CE_DPM_STATE_STORE                 (1 << 4)
+#define _PSB_CE_DPM_REACHED_MEM_THRESH          (1 << 3)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_GBL           (1 << 2)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_MT            (1 << 1)
+#define _PSB_CE_DPM_3D_MEM_FREE                 (1 << 0)
+
+#define PSB_CR_PDS_CACHE_STATUS                 (SGX_BASE + 0x0138)
+
+#define PSB_CR_PDS_CACHE_HOST_ENABLE            (SGX_BASE + 0x013C)
+
+#define PSB_CR_PDS_CACHE_HOST_CLEAR             (SGX_BASE + 0x0140)
+#define _PSB_CPC_DSC1_INV3                      (1 << 8)
+#define _PSB_CPC_DSC1_INV2                      (1 << 7)
+#define _PSB_CPC_DSC1_INV1                      (1 << 6)
+#define _PSB_CPC_DSC1_INV0                      (1 << 5)
+#define _PSB_CPC_DSC0_INV3                      (1 << 4)
+#define _PSB_CPC_DSC0_INV2                      (1 << 3)
+#define _PSB_CPC_DSC0_INV1                      (1 << 2)
+#define _PSB_CPC_DSC0_INV0                      (1 << 1)
+#define _PSB_CPC_CSC_INV                        (1 << 0)
+
+/* 0x200 - 0x300 */
+#define PSB_CR_VDM_START                        (SGX_BASE + 0x0200)
+#define _PSB_CV_START_PULSE                     (1 << 0)
+
+#define PSB_CR_TE_TPCCONTROL                    (SGX_BASE + 0x0224)
+#define _PSB_CT_TPCCONTROL_CLEAR                (1 << 31)
+#define _PSB_CT_TPCCONTROL_FLUSH                (1 << 30)
+
+#define PSB_CR_TE_RGNBBOX_X                     (SGX_BASE + 0x0228)
+#define _PSB_CT_RGNBOX_X_MAX_SHIFT              (16)
+#define _PSB_CT_RGNBOX_X_MAX_MASK               (0x1FF << 16)
+#define _PSB_CT_RGNBOX_X_MIN_SHIFT              (0)
+#define _PSB_CT_RGNBOX_X_MIN_MASK               (0x1FF << 0)
+
+#define PSB_CR_TE_RGNBBOX_Y                     (SGX_BASE + 0x022C)
+#define _PSB_CT_RGNBOX_Y_MAX_SHIFT              (16)
+#define _PSB_CT_RGNBOX_Y_MAX_MASK               (0x1FF << 16)
+#define _PSB_CT_RGNBOX_Y_MIN_SHIFT              (0)
+#define _PSB_CT_RGNBOX_Y_MIN_MASK               (0x1FF << 0)
+
+#define PSB_CR_MTE_OTPM_OP                      (SGX_BASE + 0x024C)
+#define _PSB_CMO_OP_CSM_FLUSH                   (1 << 2)
+#define _PSB_CMO_OP_CSM_LOAD                    (1 << 1)
+#define _PSB_CMO_OP_CSM_INV                     (1 << 0)
+
+#define PSB_CR_TE_DIAG1                         (SGX_BASE + 0x0280)
+#define _PSB_CT_DIAG1_PRERGNPRITILE_COUNT_MASK  (0xFFFFFFFF)
+
+#define PSB_CR_TE_DIAG2                         (SGX_BASE + 0x0284)
+#define _PSB_CT_DIAG2_POSTRGNPRITILE_COUNT_MASK (0xFFFFFFFF)
+
+#define PSB_CR_TE_DIAG3                         (SGX_BASE + 0x0288)
+#define _PSB_CT_DIAG3_PREPTEPRITILE_COUNT_MASK  (0xFFFFFFFF)
+
+#define PSB_CR_TE_DIAG4                         (SGX_BASE + 0x028C)
+#define _PSB_CT_DIAG4_POSTPTEPRITILE_COUNT_MASK (0xFFFFFFFF)
+
+#define PSB_CR_TE_DIAG5                         (SGX_BASE + 0x0290)
+#define _PSB_CT_DIAG5_PSGCTLDWORD_COUNT_MASK    (0xFFFFFFFF)
+
+#define PSB_CR_TE_DIAG6                         (SGX_BASE + 0x0294)
+#define _PSB_CT_DIAG6_PSGRGNHDR_COUNT_MASK      (0xFFFF << 0)
+
+#define PSB_CR_TE_DIAG7                         (SGX_BASE + 0x0298)
+#define _PSB_CT_DIAG7_TPCREADREQ_COUNT_SHIFT    (16)
+#define _PSB_CT_DIAG7_TPCREADREQ_COUNT_MASK     (0xFFFF << 16)
+#define _PSB_CT_DIAG7_TPCREADHIT_COUNT_SHIFT    (0)
+#define _PSB_CT_DIAG7_TPCREADHIT_COUNT_MASK     (0xFFFF << 0)
+
+#define PSB_CR_TE_DIAG8                         (SGX_BASE + 0x029C)
+#define _PSB_CT_DIAG8_TPCSTATEINV_COUNT_SHIFT   (16)
+#define _PSB_CT_DIAG8_TPCSTATEINV_COUNT_MASK    (0xFFFF << 16)
+#define _PSB_CT_DIAG8_TPCWRITEHIT_COUNT_SHIFT   (0)
+#define _PSB_CT_DIAG8_TPCWRITEHIT_COUNT_MASK    (0xFFFF << 0)
+
+/* 0x400 - 0x500 */
+#define PSB_CR_ISP_START_RENDER                 (SGX_BASE + 0x0428)
+#define _PSB_CI_START_RENDER_PULSE              (1 << 0)
+
+#define PSB_CR_TSP_PARAMETER_CACHE              (SGX_BASE + 0x043C)
+#define _PSB_CTP_CACHE_INVALIDATE               (1 << 0)
+
+/* 0x600 - 0x700 */
+
+#define PSB_CR_DPM_3D_PAGE_TABLE_BASE           (SGX_BASE + 0x0600)
+#define _PSB_CD3PT_BASE_ADDR_SHIFT              (4)//128-bit aligned address
+
+#define PSB_CR_DPM_3D_FREE_LIST                 (SGX_BASE + 0x0604)
+#define _PSB_CD3F_LIST_TAIL_SHIFT               (16)
+#define _PSB_CD3F_LIST_TAIL_MASK                (0xFFFF << 16)
+#define _PSB_CD3F_LIST_HEAD_SHIFT               (0)
+#define _PSB_CD3F_LIST_HEAD_MASK                (0xFFFF << 0)
+
+#define PSB_CR_DPM_HOST_DALLOC_PAGE_TABLE_BASE  (SGX_BASE + 0x0608)
+#define _PSB_CDHDPT_BASE_ADDR_SHIFT             (4)//128-bit aligned address
+
+#define PSB_CR_DPM_HOST_DALLOC_FREE_LIST        (SGX_BASE + 0x060C)
+#define _PSB_CDHDF_LIST_TAIL_SHIFT              (16)
+#define _PSB_CDHDF_LIST_TAIL_MASK               (0xFFFF << 16)
+#define _PSB_CDHDF_LIST_HEAD_SHIFT              (0)
+#define _PSB_CDHDF_LIST_HEAD_MASK               (0xFFFF << 0)
+
+#define PSB_CR_DPM_HOST_ALLOC_PAGE_TABLE_BASE   (SGX_BASE + 0x0610)
+#define _PSB_CDHAPT_BASE_ADDR_SHIFT             (4)//128-bit aligned address
+
+#define PSB_CR_DPM_HOST_ALLOC_FREE_LIST         (SGX_BASE + 0x0614)
+#define _PSB_CDHAF_LIST_TAIL_SHIFT              (16)
+#define _PSB_CDHAF_LIST_TAIL_MASK               (0xFFFF << 16)
+#define _PSB_CDHAF_LIST_HEAD_SHIFT              (0)
+#define _PSB_CDHAF_LIST_HEAD_MASK               (0xFFFF << 0)
+
+#define PSB_CR_DPM_TA_ALLOC_PAGE_TABLE_BASE     (SGX_BASE + 0x0618)
+#define _PSB_CDTAPT_BASE_ADDR_SHIFT             (4)//128-bit aligned address
+
+#define PSB_CR_DPM_TA_ALLOC_FREE_LIST           (SGX_BASE + 0x061C)
+#define _PSB_CDTAF_LIST_TAIL_SHIFT              (16)
+#define _PSB_CDTAF_LIST_TAIL_MASK               (0xFFFF << 16)
+#define _PSB_CDTAF_LIST_HEAD_SHIFT              (0)
+#define _PSB_CDTAF_LIST_HEAD_MASK               (0xFFFF << 0)
+
+
+#define PSB_CR_DPM_TA_PAGE_THRESHOLD            (SGX_BASE + 0x0620)
+#define _PSB_CDTP_THRESHOLD_VALUE_SHIFT         (0)
+#define _PSB_CDTP_THRESHOLD_VALUE_MASK          (0xFFFF << 0)
+
+#define PSB_CR_DPM_ZLS_PAGE_THRESHOLD           (SGX_BASE + 0x0624)
+#define _PSB_CDZP_THRESHOLD_VALUE_SHIFT         (0)
+#define _PSB_CDZP_THRESHOLD_VALUE_MASK          (0xFFFF << 0)
+
+#define PSB_CR_DPM_TA_GLOBAL_LIST               (SGX_BASE + 0x0628)
+#define _PSB_CDTG_LIST_POLICY                   (1 << 16)
+#define _PSB_CDTG_LIST_SIZE_SHIFT               (0)
+#define _PSB_CDTG_LIST_SIZE_MASK                (0xFFFF << 0)
+
+#define PSB_CR_DPM_STATE_CONTEXT_ID             (SGX_BASE + 0x0630)
+#define _PSB_CDSC_ID_ALLOC                      (1 << 2)
+#define _PSB_CDSC_ID_DALLOC                     (1 << 1)
+#define _PSB_CDSC_ID_LS                         (1 << 0)
+
+#define PSB_CR_DPM_3D_DEALLOCATE                (SGX_BASE + 0x063C)
+#define _PSB_CD3_DEALLOCATE_ENABLE              (1 << 1)
+#define _PSB_CD3_DEALLOCATE_GLOBAL              (1 << 0)
+
+#define PSB_CR_DPM_ALLOC                        (SGX_BASE + 0x0640)
+#define _PSB_CD_ALLOC_PAGE_OUTOFMEMORY          (1 << 17)
+#define _PSB_CD_ALLOC_PAGE_VALID                (1 << 16)
+#define _PSB_CD_ALLOC_PAGE_SHIFT                (0)
+#define _PSB_CD_ALLOC_PAGE_MASK                 (0xFFFF << 0)
+
+#define PSB_CR_DPM_DALLOC                       (SGX_BASE + 0x0644)
+#define _PSB_CD_DALLOC_PAGE_FREE                (1 << 16)
+#define _PSB_CD_DALLOC_PAGE_SHIFT               (0)
+#define _PSB_CD_DALLOC_PAGE_MASK                (0xFFFF << 0)
+
+#define PSB_CR_DPM_TA_ALLOC                     (SGX_BASE + 0x0648)
+#define _PSB_CDT_ALLOC_FREE_LIST_PREVIOUS_SHIFT (16)
+#define _PSB_CDT_ALLOC_FREE_LIST_PREVIOUS_MASK  (0xFFFF << 16)
+
+#define PSB_CR_DPM_3D                           (SGX_BASE + 0x064C)
+#define _PSB_CD_3D_FREE_LIST_PREVIOUS_SHIFT     (16)
+#define _PSB_CD_3D_FREE_LIST_PREVIOUS_MASK      (0xFFFF << 16)
+
+#define PSB_CR_DPM_HOST_DALLOC                  (SGX_BASE + 0x0650)
+#define _PSB_CDH_DALLOC_FREE_LIST_PREVIOUS_SHIFT (16)
+#define _PSB_CDH_DALLOC_FREE_LIST_PREVIOUS_MASK (0xFFFF << 16)
+
+#define PSB_CR_DPM_HOST_ALLOC                   (SGX_BASE + 0x0654)
+#define _PSB_CDH_ALLOC_FREE_LIST_PREVIOUS_SHIFT (16)
+#define _PSB_CDH_ALLOC_FREE_LIST_PREVIOUS_MASK  (0xFFFF << 16)
+
+#define PSB_CR_DPM_TASK_3D_FREE                 (SGX_BASE + 0x0680)
+#define _PSB_CDT3_FREE_LOAD                     (1 << 0)
+
+#define PSB_CR_DPM_TASK_TA_FREE                 (SGX_BASE + 0x0684)
+#define _PSB_CDTT_FREE_LOAD                     (1 << 0)
+
+#define PSB_CR_DPM_TASK_HOST_FREE               (SGX_BASE + 0x0688)
+#define _PSB_CDTH_FREE_LOAD                     (1 << 0)
+
+#define PSB_CR_DPM_TASK_DHOST_FREE              (SGX_BASE + 0x0690)
+#define _PSB_CDTD_FREE_LOAD                     (1 << 0)
+
+#define PSB_CR_DPM_TASK_STATE                   (SGX_BASE + 0x0694)
+#define _PSB_CDT_STATE_LOAD                     (1 << 2)
+#define _PSB_CDT_STATE_CLEAR                    (1 << 1)
+#define _PSB_CDT_STATE_STORE                    (1 << 0)
+
+#define PSB_CR_DPM_TASK_CONTROL                 (SGX_BASE + 0x0698)
+#define _PSB_CDT_CONTROL_LOAD                   (1 << 2)
+#define _PSB_CDT_CONTROL_CLEAR                  (1 << 1)
+#define _PSB_CDT_CONTROL_STORE                  (1 << 0)
+
+#define PSB_CR_DPM_OUTOFMEM                     (SGX_BASE + 0x069C)
+#define _PSB_CD_OUTOFMEM_ABORTALL               (1 << 2)
+#define _PSB_CD_OUTOFMEM_ABORT                  (1 << 1)
+#define _PSB_CD_OUTOFMEM_RESTART                (1 << 0)
+
+#define PSB_CR_DPM_FREE_CONTEXT                 (SGX_BASE + 0x06A0)
+#define _PSB_CDF_CONTEXT_NOW                    (1 << 0)
+
+#define PSB_CR_DPM_3D_TIMEOUT                   (SGX_BASE + 0x06A4)
+#define _PSB_CD3_TIMEOUT_NOW                    (1 << 0)
+
+#define PSB_CR_DPM_TA_EVM                       (SGX_BASE + 0x06A8)
+#define _PSB_CDT_EVM_INIT                       (1 << 0)
+
+/* 0x700 - 0x800 */
+
+#define PSB_CR_DPM_HOST_DALLOC_FREE_LIST_STATUS1 (SGX_BASE + 0x0708)
+#define _PSB_CDHDFL_STATUS1_TAIL_SHIFT          (16)
+#define _PSB_CDHDFL_STATUS1_TAIL_MASK           (0xFFFF << 16)
+#define _PSB_CDHDFL_STATUS1_HEAD_SHIFT          (0)
+#define _PSB_CDHDFL_STATUS1_HEAD_MASK           (0xFFFF << 0)
+
+#define PSB_CR_DPM_PAGE_STATUS                  (SGX_BASE + 0x0724)
+#define _PSB_CDP_STATUS_TA_SHIFT                (16)
+#define _PSB_CDP_STATUS_TA_MASK                 (0xFFFF << 16)
+#define _PSB_CDP_STATUS_TOTAL_SHIFT             (0)
+#define _PSB_CDP_STATUS_TOTAL_MASK              (0xFFFF << 0)
+
+#define PSB_CR_DPM_GLOBAL_PAGE_STATUS           (SGX_BASE + 0x072C)
+#define _PSB_CDGP_STATUS_TA_SHIFT               (16)
+#define _PSB_CDGP_STATUS_TA_MASK                (0xFFFF << 16)
+#define _PSB_CDGP_STATUS_TOTAL_SHIFT            (0)
+#define _PSB_CDGP_STATUS_TOTAL_MASK             (0xFFFF << 0)
+
+#define PSB_CR_CACHE_CTRL                       (SGX_BASE + 0x0804)
+#define _PSB_CC_CTRL_L0P1OFF                    (1 << 30)
+#define _PSB_CC_CTRL_L0P0OFF                    (1 << 29)
+#define _PSB_CC_CTRL_INVALIDATE                 (1 << 28)
+#define _PSB_CC_CTRL_L1P1OFF                    (1 << 26)
+#define _PSB_CC_CTRL_L1P0OFF                    (1 << 25)
+#define _PSB_CC_CTRL_L2OFF                      (1 << 24)
+#define _PSB_CC_CTRL_PARTDM3_SHIFT              (12)
+#define _PSB_CC_CTRL_PARTDM3_MASK               (0xF << 12)
+#define _PSB_CC_CTRL_PARTDM2_SHIFT              (8)
+#define _PSB_CC_CTRL_PARTDM2_MASK               (0xF << 8)
+#define _PSB_CC_CTRL_PARTDM1_SHIFT              (4)
+#define _PSB_CC_CTRL_PARTDM1_MASK               (0xF << 4)
+#define _PSB_CC_CTRL_PARTDM0_SHIFT              (0)
+#define _PSB_CC_CTRL_PARTDM0_MASK               (0xF << 0)
+
+/* 0xa00 - 0xb00 */
+#define PSB_CR_USE_CACHE                        (SGX_BASE + 0x0A08)
+#define _PSB_CU_CACHE_INVALIDATE                (1 << 0)
+
+/* USSE register definitions */
+
+/* USSE/PDS - 0xA00-0xBFF */
+
+#define PSB_CR_USE_CTRL                         (SGX_BASE + 0x0A00)
+#define _PSB_CU_CTRL_REGBOUND_ZERO              (1 << 19)
+#define _PSB_CU_CTRL_REGBOUND_ZERO_R1           (0 << 19)
+#define _PSB_CU_CTRL_INSTLIMIT_SHIFT            (14)
+#define _PSB_CU_CTRL_INSTLIMIT_MASK             (0x1F << 14)
+#define _PSB_CU_CTRL_ST_TTE_SCALE_SHIFT         (12)
+#define _PSB_CU_CTRL_ST_TTE_SCALE_MASK          (0x3 << 12)
+#define _PSB_CU_CTRL_CACHE_TTE_SHIFT            (4)
+#define _PSB_CU_CTRL_CACHE_TTE_MASK             (0xFF << 4)
+#define _PSB_CU_CTRL_KILL_MODE_SHIFT            (2)
+#define _PSB_CU_CTRL_KILL_MODE_MASK             (0x3 << 2)
+#define _PSB_CU_CTRL_KILL_MODE_OFF              (0 << 2)
+#define _PSB_CU_CTRL_KILL_MODE_FLUSH            (1 << 2)
+#define _PSB_CU_CTRL_KILL_MODE_KILL             (2 << 2)
+#define _PSB_CU_CTRL_KILL_DM_SHIFT              (0)
+#define _PSB_CU_CTRL_KILL_DM_MASK               (0x3 << 0)
+
+
+#define PSB_CR_USE_CODE_BASE(i)                 (SGX_BASE + (0x0A0C + ((i) << 2)))
+#define _PSB_CUC_BASE_DM_SHIFT                  (25)
+#define _PSB_CUC_BASE_DM_MASK                   (0x3 << 25)
+#define _PSB_CUC_BASE_ADDR_SHIFT                (0) // 1024-bit aligned address?
+#define _PSB_CUC_BASE_ADDR_ALIGNSHIFT           (7)
+#define _PSB_CUC_BASE_ADDR_MASK                 (0x1FFFFFF << 0)
+#define _PSB_CUC_DM_VERTEX                      (0)
+#define _PSB_CUC_DM_PIXEL                       (1)
+#define _PSB_CUC_DM_RESERVED                    (2)
+#define _PSB_CUC_DM_EDM                         (3)
+
+#define SGX_MAX_USSE_THRDS                      16
+#define PSB_USE_OFFSET_MASK                     0x0007FFFF
+#define PSB_USE_OFFSET_SIZE                     (SGX_USE_OFFSET_MASK + 1)
+#define PSB_CR_USE_CODE_BASE0                   (SGX_BASE + 0x0A0C)
+#define PSB_CR_USE_CODE_BASE1                   (SGX_BASE + 0x0A10)
+#define PSB_CR_USE_CODE_BASE2                   (SGX_BASE + 0x0A14)
+#define PSB_CR_USE_CODE_BASE3                   (SGX_BASE + 0x0A18)
+#define PSB_CR_USE_CODE_BASE4                   (SGX_BASE + 0x0A1C)
+#define PSB_CR_USE_CODE_BASE5                   (SGX_BASE + 0x0A20)
+#define PSB_CR_USE_CODE_BASE6                   (SGX_BASE + 0x0A24)
+#define PSB_CR_USE_CODE_BASE7                   (SGX_BASE + 0x0A28)
+#define PSB_CR_USE_CODE_BASE8                   (SGX_BASE + 0x0A2C)
+#define PSB_CR_USE_CODE_BASE9                   (SGX_BASE + 0x0A30)
+#define PSB_CR_USE_CODE_BASE10                  (SGX_BASE + 0x0A34)
+#define PSB_CR_USE_CODE_BASE11                  (SGX_BASE + 0x0A38)
+#define PSB_CR_USE_CODE_BASE12                  (SGX_BASE + 0x0A3C)
+#define PSB_CR_USE_CODE_BASE13                  (SGX_BASE + 0x0A40)
+#define PSB_CR_USE_CODE_BASE14                  (SGX_BASE + 0x0A44)
+#define PSB_CR_USE_CODE_BASE15                  (SGX_BASE + 0x0A48)
+
+#define PSB_CR_EVENT_PDS_ENABLE                 (SGX_BASE + 0x0A58)
+#define _PSB_CEP_ENABLE_TIMER                   (1 << 29)
+#define _PSB_CEP_ENABLE_TA_DPM_FAULT            (1 << 28)
+#define _PSB_CEP_ENABLE_TWOD_COMPLETE           (1 << 27)
+#define _PSB_CEP_ENABLE_MADD_CACHE_INVALCOMPLETE (1 << 26)
+#define _PSB_CEP_ENABLE_DPM_OUT_OF_MEMORY_ZLS   (1 << 25)
+#define _PSB_CEP_ENABLE_DPM_TA_MEM_FREE         (1 << 24)
+#define _PSB_CEP_ENABLE_ISP_END_PASS            (1 << 23)
+#define _PSB_CEP_ENABLE_DPM_INITEND             (1 << 22)
+#define _PSB_CEP_ENABLE_OTPM_LOADED             (1 << 21)
+#define _PSB_CEP_ENABLE_OTPM_INV                (1 << 20)
+#define _PSB_CEP_ENABLE_OTPM_FLUSHED            (1 << 19)
+#define _PSB_CEP_ENABLE_PIXELBE_END_RENDER      (1 << 18)
+#define _PSB_CEP_ENABLE_ISP_HALT                (1 << 17)
+#define _PSB_CEP_ENABLE_ISP_VISIBILITY_FAIL     (1 << 16)
+#define _PSB_CEP_ENABLE_BREAKPOINT              (1 << 15)
+#define _PSB_CEP_ENABLE_SW_EVENT                (1 << 14)
+#define _PSB_CEP_ENABLE_TA_FINISHED             (1 << 13)
+#define _PSB_CEP_ENABLE_TA_TERMINATE            (1 << 12)
+#define _PSB_CEP_ENABLE_TPC_CLEAR               (1 << 11)
+#define _PSB_CEP_ENABLE_TPC_FLUSH               (1 << 10)
+#define _PSB_CEP_ENABLE_DPM_CONTROL_CLEAR       (1 << 9)
+#define _PSB_CEP_ENABLE_DPM_CONTROL_LOAD        (1 << 8)
+#define _PSB_CEP_ENABLE_DPM_CONTROL_STORE       (1 << 7)
+#define _PSB_CEP_ENABLE_DPM_STATE_CLEAR         (1 << 6)
+#define _PSB_CEP_ENABLE_DPM_STATE_LOAD          (1 << 5)
+#define _PSB_CEP_ENABLE_DPM_STATE_STORE         (1 << 4)
+#define _PSB_CEP_ENABLE_DPM_REACHED_MEM_THRESH  (1 << 3)
+#define _PSB_CEP_ENABLE_DPM_OUT_OF_MEMORY_GBL   (1 << 2)
+#define _PSB_CEP_ENABLE_DPM_OUT_OF_MEMORY_MT    (1 << 1)
+#define _PSB_CEP_ENABLE_DPM_3D_MEM_FREE         (1 << 0)
+
+#define PSB_CR_DMS_CTRL                         (SGX_BASE + 0x0A74)
+#define _PSB_CD_CTRL_MAX_NUM_VERTEX_PARTITIONS_SHIFT (25)
+#define _PSB_CD_CTRL_MAX_NUM_VERTEX_PARTITIONS_MASK  (0x7 << 25)
+#define _PSB_CD_CTRL_MAX_NUM_PIXEL_PARTITIONS_SHIFT  (22)
+#define _PSB_CD_CTRL_MAX_NUM_PIXEL_PARTITIONS_MASK   (0x7 << 22)
+#define _PSB_CD_CTRL_MAX_NUM_EDM_TASKS_SHIFT    (16)
+#define _PSB_CD_CTRL_MAX_NUM_EDM_TASKS_MASK     (0x3F << 16)
+#define _PSB_CD_CTRL_MAX_NUM_VERTEX_TASKS_SHIFT (10)
+#define _PSB_CD_CTRL_MAX_NUM_VERTEX_TASKS_MASK  (0x3F << 10)
+#define _PSB_CD_CTRL_MAX_NUM_PIXEL_TASKS_SHIFT  (4)
+#define _PSB_CD_CTRL_MAX_NUM_PIXEL_TASKS_MASK   (0x3F << 4)
+#define _PSB_CD_CTRL_DISABLE_DM_SHIFT           (0)
+#define _PSB_CD_CTRL_DISABLE_DM_MASK            (0xF << 0)
+#define _PSB_CD_CTRL_DISABLE_DM_VERTEX          (1 << 0)
+#define _PSB_CD_CTRL_DISABLE_DM_PIXEL           (1 << 1)
+#define _PSB_CD_CTRL_DISABLE_DM_EVENT           (1 << 2)
+#define _PSB_CD_CTRL_DISABLE_DM_LOOPBACK        (1 << 3)
+
+#define PSB_CR_DMS_AGE                          (SGX_BASE + 0x0A78)
+#define _PSB_CD_AGE_ENABLE                      (1 << 16)
+#define _PSB_CD_AGE_VALUE_SHIFT                 (0)
+#define _PSB_CD_AGE_VALUE_MASK                  (0xFFFF << 0)
+
+#define PSB_CR_USE_G0                           (SGX_BASE + 0x0A7C)
+#define _PSB_CU_G0_VALUE_SHIFT                  (0)
+#define _PSB_CU_G0_VALUE_MASK                   (0xFF << 0)
+
+#define PSB_CR_USE_G1                           (SGX_BASE + 0x0A80)
+#define _PSB_CU_G1_VALUE_SHIFT                  (0)
+#define _PSB_CU_G1_VALUE_MASK                   (0xFF << 0)
+
+#define PSB_CR_PDS_EXEC_BASE                    (SGX_BASE + 0x0AB8)
+#define _PSB_CR_PDS_EXEC_BASE_ADDR_SHIFT        (20)/* 1MB aligned address */
+#define _PSB_CR_PDS_EXEC_BASE_ADDR_ALIGNSHIFT   (20)
+
+#define PSB_CR_USE0_DM_SLOT                     (SGX_BASE + 0x0AA4)
+
+#define PSB_CR_USE1_DM_SLOT                     (SGX_BASE + 0x0AA8)
+
+#define PSB_CR_USE_TMPREG                       (SGX_BASE + 0x0AAC)
+#define _PSB_CU_TMPREG_INIT_SHIFT               (3)
+#define _PSB_CU_TMPREG_INIT_MASK                (0x1F << 3)
+#define _PSB_CU_TMPREG_SIZE_SHIFT               (0)
+#define _PSB_CU_TMPREG_SIZE_MASK                (0x7 << 0)
+
+#define PSB_CR_EVENT_TIMER                      (SGX_BASE + 0x0ACC)
+#define _PSB_CE_TIMER_ENABLE                    (1 << 24)
+#define _PSB_CE_TIMER_VALUE_SHIFT               (0)
+#define _PSB_CE_TIMER_VALUE_MASK                (0xFFFFFF << 0)
+
+#define PSB_CR_PDS                              (SGX_BASE + 0x0ABC)
+#define _PSB_C_PDS_DOUT_TIMEOUT_DISABLE         (1 << 6)
+#define _PSB_C_PDS_ATTRIBUTE_CHUNK_START_SHIFT  (0)
+#define _PSB_C_PDS_ATTRIBUTE_CHUNK_START_MASK   (0x3F << 0)
+
+#define PSB_CR_PDS_INV0                         (SGX_BASE + 0x0AD0)
+
+#define PSB_CR_PDS_INV1                         (SGX_BASE + 0x0AD4)
+
+#define PSB_CR_PDS_INV2                         (SGX_BASE + 0x0AD8)
+
+#define PSB_CR_PDS_INV3                         (SGX_BASE + 0x0ADC)
+#define _PSB_CP_INV_DSC                         (1 << 0)
+
+#define PSB_CR_PDS_INV_CSC                      (SGX_BASE + 0x0AE0)
+#define _PSB_CPI_CSC_KICK                       (1 << 0)
+
+/* 0xb00 - 0xc00 */
+#define PSB_CR_USE0_SERV_PIXEL                  (SGX_BASE + 0x0B08)
+#define _PSB_CUS_PIXEL_EMPTY                    (1 << 16)
+#define _PSB_CUS_PIXEL_COUNT_SHIFT              (0)
+#define _PSB_CUS_PIXEL_COUNT_MASK               (0xFFFF << 0)
+
+#define PSB_CR_USE0_SERV_VERTEX                 (SGX_BASE + 0x0B0C)
+#define _PSB_CUS_VERTEX_EMPTY                   (1 << 16)
+#define _PSB_CUS_VERTEX_COUNT_SHIFT             (0)
+#define _PSB_CUS_VERTEX_COUNT_MASK              (0xFFFF << 0)
+
+#define PSB_CR_USE0_SERV_EVENT                  (SGX_BASE + 0x0B10)
+#define _PSB_CUS_EVENT_EMPTY                    (1 << 16)
+#define _PSB_CUS_EVENT_COUNT_SHIFT              (0)
+#define _PSB_CUS_EVENT_COUNT_MASK               (0xFFFF << 0)
+
+#define PSB_CR_USE1_SERV_PIXEL                  (SGX_BASE + 0x0B14)
+
+#define PSB_CR_USE1_SERV_VERTEX                 (SGX_BASE + 0x0B18)
+
+#define PSB_CR_USE1_SERV_EVENT                  (SGX_BASE + 0x0B1C)
+
+/* 0xc00 - 0xd00 */
+/* BIF register definitions */
+#define PSB_CR_BIF_CTRL                         (SGX_BASE + 0x0C00)
+#define _PSB_CB_CTRL_CLEAR_FAULT                (1 << 4)
+#define _PSB_CB_CTRL_INVALDC                    (1 << 3)
+#define _PSB_CB_CTRL_FLUSH                      (1 << 2)
+#define _PSB_MMU_ER_MASK                        0x0001FF00
+#define _PSB_MMU_ER_HOST                        (1 << 16)
+
+#define PSB_CR_BIF_INT_STAT                     (SGX_BASE + 0x0C04)
+
+#define PSB_CR_BIF_FAULT                        (SGX_BASE + 0x0C08)
+#define _PSB_CBI_STAT_PF_N_RW                   (1 << 14)
+#define _PSB_CBI_STAT_FAULT_SHIFT               (0)
+#define _PSB_CBI_STAT_FAULT_MASK                (0x3FFF << 0)
+#define _PSB_CBI_STAT_FAULT_CACHE               (1 << 1)
+#define _PSB_CBI_STAT_FAULT_TA                  (1 << 2)
+#define _PSB_CBI_STAT_FAULT_VDM                 (1 << 3)
+#define _PSB_CBI_STAT_FAULT_2D                  (1 << 4)
+#define _PSB_CBI_STAT_FAULT_PBE                 (1 << 5)
+#define _PSB_CBI_STAT_FAULT_TSP                 (1 << 6)
+#define _PSB_CBI_STAT_FAULT_ISP                 (1 << 7)
+#define _PSB_CBI_STAT_FAULT_USSEPDS             (1 << 8)
+#define _PSB_CBI_STAT_FAULT_HOST                (1 << 9)
+
+#define PSB_CR_BIF_BANK_SET                     (SGX_BASE + 0x0C74)
+#define _PSB_CBB_SET_SELECT_SHIFT               (0)
+#define _PSB_CBB_SET_SELECT_MASK                (0x3FF << 0)
+#define _PSB_CBB_SET_SELECT_DPM_TA              (0 << 9)
+#define _PSB_CBB_SET_SELECT_DPM_3D              (1 << 9)
+#define _PSB_CBB_SET_SELECT_EDM_B0              (0 << 8)
+#define _PSB_CBB_SET_SELECT_EDM_B1              (1 << 8)
+#define _PSB_CBB_SET_SELECT_TA_B0               (0 << 6)
+#define _PSB_CBB_SET_SELECT_TA_B0B1             (1 << 6)
+#define _PSB_CBB_SET_SELECT_TA_B1B0             (2 << 6)
+#define _PSB_CBB_SET_SELECT_TA_B1               (3 << 6)
+#define _PSB_CBB_SET_SELECT_HOST_B0             (0 << 4)
+#define _PSB_CBB_SET_SELECT_HOST_B1             (3 << 4)
+#define _PSB_CBB_SET_SELECT_3D_B0               (0 << 2)
+#define _PSB_CBB_SET_SELECT_3D_B0B1             (1 << 2)
+#define _PSB_CBB_SET_SELECT_3D_B1B0             (2 << 2)
+#define _PSB_CBB_SET_SELECT_3D_B1               (3 << 2)
+#define _PSB_CBB_SET_SELECT_2D_B0               (0 << 0)
+#define _PSB_CBB_SET_SELECT_2D_B1               (3 << 0)
+
+#define PSB_CR_BIF_BANK0                        (SGX_BASE + 0x0C78)
+#define PSB_CR_BIF_BANK1                        (SGX_BASE + 0x0C7C)
+
+#define _PSB_CB_BANK_INDEX_2D_SHIFT             (16)
+#define _PSB_CB_BANK_INDEX_2D_MASK              (0xF << 16)
+#define _PSB_CB_BANK_INDEX_3D_SHIFT             (12)
+#define _PSB_CB_BANK_INDEX_3D_MASK              (0xF << 12)
+#define _PSB_CB_BANK_INDEX_HOST_SHIFT           (8)
+#define _PSB_CB_BANK_INDEX_HOST_MASK            (0xF << 8)
+#define _PSB_CB_BANK_INDEX_TA_SHIFT             (4)
+#define _PSB_CB_BANK_INDEX_TA_MASK              (0xF << 4)
+#define _PSB_CB_BANK_INDEX_EDM_SHIFT            (0)
+#define _PSB_CB_BANK_INDEX_EDM_MASK             (0xF << 0)
+
+#define PSB_CR_BIF_DIR_LIST_BASE0               (SGX_BASE + 0x0C84)
+#define PSB_CR_BIF_DIR_LIST_BASE1               (SGX_BASE + 0x0C38)
+#define PSB_CR_BIF_TWOD_REQ_BASE                (SGX_BASE + 0x0C88)
+
+#define PSB_CR_BIF_TA_REQ_BASE                  (SGX_BASE + 0x0C90)
+#define _PSB_CBTR_BASE_ADDR_SHIFT               (20) // 1MB aligned address
+
+#define PSB_CR_BIF_MEM_ARB_CONFIG               (SGX_BASE + 0x0CA0)
+#define _PSB_CBMA_CONFIG_TTE_THRESH_SHIFT       (12)
+#define _PSB_CBMA_CONFIG_TTE_THRESH_MASK        (0xFFF << 12)
+#define _PSB_CBMA_CONFIG_BEST_CNT_SHIFT         (4)
+#define _PSB_CBMA_CONFIG_BEST_CNT_MASK          (0xFF << 4)
+#define _PSB_CBMA_CONFIG_PAGE_SIZE_SHIFT        (0)
+#define _PSB_CBMA_CONFIG_PAGE_SIZE_MASK         (0xF << 0)
+
+#define PSB_CR_BIF_3D_REQ_BASE                  (SGX_BASE + 0x0CAC)
+#define _PSB_CB3R_BASE_ADDR_ALIGNSHIFT          (20)
+#define _PSB_CB3R_BASE_ADDR_SHIFT               (20) // 1MB aligned address
+
+/* 0xe00 - 0xf00 */
+#define PSB_EUR_CR_2D_SOCIF                     (SGX_BASE + 0x0e18)
+
+#define PSB_EUR_CR_2D_BLIT_STATUS               (SGX_BASE + 0x0e04)
+
+#endif /* _REGS_H_ */
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/rb.h b/drivers/gpu/drm/emgd/emgd/include/rb.h
new file mode 100644
index 0000000..8e0c166
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/rb.h
@@ -0,0 +1,186 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: rb.h
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This header file describes the inter-module interface for using the
+ *  ring buffer. This is a legacy interface that is not strictly
+ *  device-independent. It is kept here because many legacy chipsets use
+ *  this interface.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _RB_H
+#define _RB_H
+
+#include <igd_rb.h>
+#include <igd_errno.h>
+
+#include <context.h>
+#include <module_init.h>
+#include <mode.h>
+
+#include <io.h>
+#include <memory.h>
+#include <sched.h>
+
+
+/*
+ * The rb_buffer contents should be treated as opaque but are defined
+ * here for the use in the inline functions below.
+ */
+typedef struct _rb_buffer {
+	unsigned int id;       /* ring index */
+	unsigned long size;    /* size of rb in bytes */
+	unsigned long tail_off;
+	unsigned long dead_off;
+	unsigned long avail;
+	unsigned long addr;    /* starting address of rb */
+	unsigned char *virt;    /* virt starting address of rb */
+	unsigned char *start;   /* ring buffer start register offset */
+	unsigned char *head;    /* ring buffer head register offset */
+	unsigned char *tail;    /* ring buffer tail register offset */
+	unsigned char *ctrl;    /* ring buffer ctrl register offset */
+	unsigned char *sync;    /* used to synchronize s/w interface
+								   * code via rb_sync() */
+	unsigned long next_sync;
+	int state;             /* on or off state */
+	unsigned long last_head_value; /* used for checking ring buf lockup,
+									* keeps last head value*/
+	os_alarm_t last_head_time; /* used for checking ring buf lockup,
+								* keeps last head time*/
+	unsigned long reservation; /* increments upon each rb_reserver(),
+								* reset to zero upon rb_update() */
+	unsigned long sync_wrap;   /* Sync number to wrap at */
+	igd_context_t * context_ptr; /*back pointer to the main driver context */
+	igd_appcontext_h appcontext; /* Appcontext that is current on the ring */
+        unsigned int skip_timeout;  /* skip the timeout check */
+	unsigned int force_reset_rb;  /* force a rb reset */
+} rb_buffer_t;
+
+
+#define MODE_GET_RING(d, p) \
+	((rb_buffer_t *)((igd_display_pipe_t *)((igd_display_context_t *)d)->pipe)->queue[p])
+
+/*
+ * Flags used exclusively by rb_reserve()
+ */
+#define RB_RESERVE_BLOCK     0x00000000
+#define RB_RESERVE_NONBLOCK  0x00000001
+
+
+/*
+ * Determine how much space is available in the ring buffer.
+ */
+unsigned long rb_avail(rb_buffer_t *buffer);
+
+
+#define MODE_PIPE_ALLOCED(d) \
+	((igd_display_pipe_t *)((igd_display_context_t *)d)->pipe)
+
+extern igd_command_t *rb_slow_reserve(rb_buffer_t *buffer,
+	unsigned long size,
+	unsigned long flags);
+/*
+ * For Debug do not use the inline ring functions. It makes it hard
+ * to add breakpoints.
+ */
+#ifdef DEBUG_BUILD_TYPE
+extern igd_command_t *rb_reserve(rb_buffer_t *buffer,
+	unsigned long size,
+	unsigned long flags);
+
+extern int rb_update(rb_buffer_t *buffer,
+	igd_command_t *addr);
+
+#else
+#ifdef CONFIG_CMD
+static __inline igd_command_t *rb_reserve(rb_buffer_t *buffer,
+	unsigned long size,
+	unsigned long flags)
+{
+	if (buffer->state == CMD_CONTROL_OFF) {
+		/* ring buffer is turned off, so don't allow a rb_reserve() */
+		buffer->context_ptr->igd_device_error_no = -IGD_ERROR_PWRDOWN;
+		return(NULL);
+	}
+
+	/*
+	 * Change size to bytes for efficiency.
+	 */
+	size = ((size<<2) + 7) & ~7;
+
+	if(buffer->reservation) {
+		buffer->avail += buffer->reservation;
+	}
+	buffer->reservation = size;
+
+	if(buffer->avail > size) {
+		buffer->avail -= size;
+		return (igd_command_t *)(buffer->virt + buffer->tail_off);
+	}
+
+	return rb_slow_reserve(buffer, size, flags);
+}
+
+
+static __inline int rb_update(rb_buffer_t *buffer,
+	igd_command_t *addr)
+{
+	unsigned long tail_off;
+/*	tail_off = (addr - buffer->virt); */
+	tail_off = (unsigned long)((unsigned char *)(addr) - buffer->virt);
+
+	buffer->reservation = 0;
+	buffer->tail_off = tail_off;
+
+	if(buffer->tail_off & 0x7) {
+		EMGD_WRITE32(0, buffer->virt + buffer->tail_off);
+		buffer->tail_off += 4;
+		buffer->avail -= 4;
+	}
+
+	EMGD_WRITE32(buffer->tail_off, buffer->tail);
+
+	return 0;
+}
+#else
+static __inline igd_command_t *rb_reserve(rb_buffer_t *buffer,
+	unsigned long size,
+	unsigned long flags)
+{
+	return NULL;
+}
+
+static __inline int rb_update(rb_buffer_t *buffer,
+	igd_command_t *addr)
+{
+	return 0;
+}
+#endif /* CONFIG_CMD */
+#endif
+
+#endif /* _RB_H */
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/reset.h b/drivers/gpu/drm/emgd/emgd/include/reset.h
new file mode 100644
index 0000000..809cb52
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/reset.h
@@ -0,0 +1,43 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: reset.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the internal header file for the reset module. It should be included
+ *  by ssigd HAL modules that need to access the reset module for initialization
+ *  and shutdown
+ *-----------------------------------------------------------------------------
+ */
+
+
+#ifndef _IGD_RESET_INIT_H
+#define _IGD_RESET_INIT_H
+
+#define RESET_FLAG_CAPTURE_SNAPSHOT         0x00000001
+#define RESET_FLAG_EXECUTE_SOFT_RESET       0x00000002
+#define RESET_FLAG_EXECUTE_HARD_RESET       0x00000003
+
+
+#endif /*_IGD_RESET_H*/
diff --git a/drivers/gpu/drm/emgd/emgd/include/sched.h b/drivers/gpu/drm/emgd/emgd/include/sched.h
new file mode 100644
index 0000000..9b33a1a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/sched.h
@@ -0,0 +1,197 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sched.h
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains Linux User-space implementations for the OAL io.h
+ *  abstractions.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OAL_LINUX_USER_SCHED_H
+#define _OAL_LINUX_USER_SCHED_H
+
+#include <config.h>
+
+#include <linux/sched.h>
+#include <linux/delay.h>
+
+typedef unsigned long os_alarm_t;
+
+static __inline os_alarm_t _linux_kernel_set_alarm(unsigned long t)
+{
+	return (msecs_to_jiffies(t) + jiffies);
+}
+
+static __inline int _linux_kernel_test_alarm(os_alarm_t t)
+{
+	return (jiffies >= t) ? 1 : 0;
+}
+
+#define OS_SET_ALARM(t) _linux_kernel_set_alarm(t)
+#define OS_TEST_ALARM(t) _linux_kernel_test_alarm(t)
+
+
+/*----------------------------------------------------------------------------
+ *  Function: OS_INIT_INTERRUPT
+ *
+ *  Description:
+ *  This function establishes the communication for sending requests for interrupt
+ *
+ *  int OS_INIT_INTERRUPT( did, mmadr )
+ *---------------------------------------------------------------------------*/
+#ifdef CONFIG_INTERRUPT
+#define OS_INIT_INTERRUPT(did, mmadr) _OS_INIT_INTERRUPT(did, mmadr)
+#else
+#define OS_INIT_INTERRUPT(did, mmadr) 0
+#endif
+
+
+
+/*----------------------------------------------------------------------------
+ * Function: OS_SCHEDULE
+ *
+ * Description:
+ *  This function can be called with the caller wished to give up processor
+ *  control until the next available timeslice. This will allow other OS tasks
+ *  to run before returning to the current context. This function should be
+ *  used with caution and observation of reentrant coding principals.
+ *
+ *  void OS_SCHEDULE( void );
+ *---------------------------------------------------------------------------*/
+
+#define OS_SCHEDULE() {									\
+	__set_current_state(TASK_INTERRUPTIBLE);					\
+	schedule_timeout(1); }
+
+#if 0
+#define OS_DELAY(usec) {					\
+    unsigned long j_timeout = usecs_to_jiffies(usec);		\
+    unsigned long j_start = jiffies;				\
+    unsigned long j_current;					\
+    do {							\
+      j_current = jiffies;					\
+    }while((j_current - j_start) < j_timeout);			\
+}
+#else 
+#define OS_DELAY(usec)	udelay(usec);
+#endif
+
+#if 0
+// Implement _OS_SLEEP at a wait-loop
+#define _OS_SLEEP(usec) {					\
+	unsigned long j_timeout = usecs_to_jiffies(usec);		\
+	unsigned long j_start = jiffies;				\
+	unsigned long j_current;					\
+	do {							\
+		j_current = jiffies;					\
+	}while((j_current - j_start) < j_timeout);			\
+}
+#else
+// Implement _OS_SLEEP as a true sleep
+
+/* We could also try TASK_UNINTERRUPTIBLE here */
+/*----------------------------------------------------------------------------
+ * Function: OS_SLEEP
+ *
+ * Parameters:
+ *  time_val: Unsigned long time value in Micro-seconds (1/1000000 of a second)
+ *            for the task to sleep.
+ *
+ * Description:
+ *  This function causes the caller to delay further processing
+ *  for the number of micro-seconds ( 1/1000000 or a second ) requested.
+ *  This function should only be used with small time values
+ *  ( < 1/100 of a second ) as lengthy sleeps could degrade the kernel
+ *  response time.
+ *
+ *  void OS_SLEEP( unsigned long time_val );
+ *---------------------------------------------------------------------------*/
+
+#define OS_SLEEP(usec) {									\
+	__set_current_state(TASK_KILLABLE);						\
+	schedule_timeout(usecs_to_jiffies(usec)); }
+#endif
+
+/*----------------------------------------------------------------------------
+ * Function: OS_UISLEEP
+ *
+ * Parameters:
+ *  time_val: Unsigned long time value in Micro-seconds (1/1000000 of a second)
+ *            for the task to sleep.
+ *
+ * Description:
+ *  This function causes the caller to delay further processing
+ *  for the number of micro-seconds ( 1/1000000 or a second ) requested.
+ *  This sleep is uninterrruptable.
+ *  This function should only be used with small time values
+ *  ( < 1/100 of a second ) as lengthy sleeps could degrade the kernel
+ *  response time.
+ *
+ *  void OS_UISLEEP( unsigned long time_val );
+ *---------------------------------------------------------------------------*/
+
+/* un interuuptable sleep */
+#define OS_UISLEEP(usec) {					\
+	__set_current_state(TASK_UNINTERRUPTIBLE);			\
+	schedule_timeout(usecs_to_jiffies(usec)); 			\
+}
+
+#ifndef OS_PTHREAD_CREATE
+typedef int os_pthread_t;
+// This function is not being used.
+// #define OS_PTHREAD_CREATE(t, a, f, p) (-1)
+#endif
+
+#ifndef OS_PTHREAD_JOIN
+// This function is not being used.
+// #define OS_PTHREAD_JOIN(t, p) (0)
+#endif
+
+/*
+ * Note, the POSIX pthread implementation does not take the thread as a
+ * parameter but it makes porting easier.
+ */
+#define UNREFERENCED_PARAMETER(parm) ((parm)=(parm))
+
+#ifndef OS_PTHREAD_EXIT
+// This function is not being used.
+// #define OS_PTHREAD_EXIT(t, r)
+#endif
+
+#ifndef OS_PTHREAD_MUTEX_INIT
+typedef struct mutex os_pthread_mutex_t;
+#define OS_PTHREAD_MUTEX_INIT(m, a) mutex_init(m)
+#endif
+
+#ifndef OS_PTHREAD_MUTEX_LOCK
+#define OS_PTHREAD_MUTEX_LOCK(m) mutex_lock_interruptible(m)
+#endif
+
+#ifndef OS_PTHREAD_MUTEX_UNLOCK
+#define OS_PTHREAD_MUTEX_UNLOCK(m) mutex_unlock(m)
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/state2d.h b/drivers/gpu/drm/emgd/emgd/include/state2d.h
new file mode 100644
index 0000000..af04e47
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/state2d.h
@@ -0,0 +1,69 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: state2d.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file is the header file for manipulating the 2D State variables.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _STATE2D_H
+#define _STATE2D_H
+
+/* IGD */
+#include <igd_render.h>
+
+typedef struct _state2d {
+    igd_rect_t dest_rect;
+	unsigned int clip_status;
+} state2d_t;
+
+#define STATE2D(ac) ((state2d_t *)ac->state2d)
+
+#define STATE2D_SET_CLIP(ac, rect)                            \
+if(ac) {                                                      \
+    OS_MEMCPY(&((state2d_t *)(ac)->state2d)->dest_rect, rect, \
+		sizeof(igd_rect_t));                                  \
+}
+ /*
+  * Checking for the 2D appcontext instead of the appcontext
+  * pointer because the state2d could be null during botched
+  * allocation.
+  */
+#define STATE2D_GET_CLIP(ac) \
+	(((ac) && ((state2d_t *)(ac)->state2d))? \
+	(&((state2d_t *)(ac)->state2d)->dest_rect):NULL)
+
+#define STATE2D_GET_CLIP_STATUS(ac) \
+	(((ac) && ((state2d_t *)(ac)->state2d))? \
+	(((state2d_t *)(ac)->state2d)->clip_status):0)
+
+#define STATE2D_SET_CLIP_STATUS(ac, s) \
+	(((ac) && ((state2d_t *)(ac)->state2d))? \
+	(((state2d_t *)(ac)->state2d)->clip_status = s):0)
+
+#endif /*_STATE2D_H */
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/appcontext.h b/drivers/gpu/drm/emgd/emgd/include/tnc/appcontext.h
new file mode 100644
index 0000000..0c76cf1
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/appcontext.h
@@ -0,0 +1,40 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: appcontext.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the inter-module header file for the client context module.
+ *  It contains data structures needed for modules to use and manipulate
+ *  the device state including hardware context switching.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _APPCONTEXT_TNC_H
+#define _APPCONTEXT_TNC_H
+
+/* reusing pouslbo structures */
+#include<plb/appcontext.h>
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/cmd.h b/drivers/gpu/drm/emgd/emgd/include/tnc/cmd.h
new file mode 100644
index 0000000..731c86a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/cmd.h
@@ -0,0 +1,39 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: cmd.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Device dependent header file for the command interface for poulsbo
+ *  devices.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _TNC_CMD_H
+#define _TNC_CMD_H
+
+/* reusing pouslbo codes */
+#include<plb/cmd.h>
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/context.h b/drivers/gpu/drm/emgd/emgd/include/tnc/context.h
new file mode 100644
index 0000000..bcd73ee
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/context.h
@@ -0,0 +1,37 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: context.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _HAL_TNC_CONTEXT_H
+#define _HAL_TNC_CONTEXT_H
+
+#include<plb/context.h>
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/igd_tnc_wa.h b/drivers/gpu/drm/emgd/emgd/include/tnc/igd_tnc_wa.h
new file mode 100644
index 0000000..7cd4aa7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/igd_tnc_wa.h
@@ -0,0 +1,133 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_tnc_wa.h
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This header file contains the Device Dependent information used with
+ *  the IEGD HAL for the Atom E6xx family of supported chips.
+ *  Note: This file should be included into a C file as <tnc/igd_tnc_wa.h> and
+ *  not <igd_tnc_wa.h> this will insure that multiple device dependent
+ *  igd_cmd.h files can be included into a single C source.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_TNC_WA_H
+#define _IGD_TNC_WA_H
+
+#define LNC_CLOCK 199500
+#define LNC_B1_OPTIMUM_MARGIN 2000
+#define LIMIT_TOTAL_CHECK_DISPLAY 10
+#define T0 0
+#define T1 1
+#define WA_TUNE \
+	((tnc_wa_timing_t *)&tune)
+/* Graphic core Revision ID for Atom E6xx stepping */
+#define TNC_A0_RID			0x2
+#define TNC_B0_RID			0x3
+#define TNC_B0_DEV3_RID		0x1
+#define TNC_B1_DEV3_RID		0x2
+#define SDVO_CRC_CTRL_REG	0x61050
+#define SDVO_BUFF_CTRL_REG	0x61170
+#define TNC_HTOTAL_TUNED	0x8000
+
+/* flag to enable clipping hardware fix in TNC B1 */
+#define IGD_CLIP_FIX_DISABLE            0x0000
+ /* Completely disable throttling */
+#define IGD_CLIP_FIX_DISABLE_THROTTLE   0x0001          
+/* Replaces the original stall_pixel from FSM with external stall from cDVO */
+#define IGD_CLIP_FIX_REPLACE_STALL      0x0002    
+#define IGD_CLIP_FIX_GLOBAL_ENABLE      0x8000
+#define CLIP_HW_FIX_DEFAULT             0x8001
+
+/*
+ * These are the register default settings for TC B1
+ * They are used for the undocumented register override feature
+ * when en_reg_override=1
+ */
+#define DISP_ARB                0x00003232
+#define FIFO_WATERMARK_1        0x3f8f0404
+#define FIFO_WATERMARK_2        0x04040f04
+#define FIFO_WATERMARK_3        0x00000000
+#define FIFO_WATERMARK_4        0x04040404
+#define FIFO_WATERMARK_5        0x04040404
+#define FIFO_WATERMARK_6        0x00000078
+#define GVD_HP_CONTROL          0x102003f2
+#define DISP_CHICKENBITS        0x0000c040
+#define BCHICKENBITS            0xffe32004
+#define BWFLUSH                 0x00000408
+
+typedef struct _tnc_wa_timing_t{
+	short htotal;
+	short delta;
+	short flag;
+	short counter;
+	unsigned int crc_red;
+	unsigned int crc_green;
+	unsigned int crc_blue;
+}tnc_wa_timing_t;
+
+typedef union
+{
+       unsigned int pixel;
+       struct
+	   {
+			   unsigned int bit0             :1;
+               unsigned int bit1             :1;
+               unsigned int bit2             :1;
+               unsigned int bit3             :1;
+               unsigned int bit4             :1;
+               unsigned int bit5             :1;
+               unsigned int bit6             :1;
+               unsigned int bit7             :1;
+               unsigned int bit8             :1;
+               unsigned int bit9             :1;
+               unsigned int bit10             :1;
+               unsigned int bit11             :1;
+               unsigned int bit12             :1;
+               unsigned int bit13             :1;
+               unsigned int bit14             :1;
+               unsigned int bit15             :1;
+               unsigned int bit16             :1;
+               unsigned int bit17             :1;
+               unsigned int bit18             :1;
+               unsigned int bit19             :1;
+               unsigned int bit20             :1;
+               unsigned int bit21             :1;
+               unsigned int bit22             :1;
+               unsigned int bitExtra          :1;
+               unsigned int bitRest           :8;
+       } bit;
+} pixel_crc_t;
+
+
+/*
+* CDVO regs structure. This is mainly used to move the CDVO reset sequence
+* to the data segment for VBIOS.
+*/
+typedef struct _cdvo_regs_t{
+	unsigned long reg;
+	unsigned long value;
+}cdvo_regs_t;
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/instr.h b/drivers/gpu/drm/emgd/emgd/include/tnc/instr.h
new file mode 100644
index 0000000..14bf85f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/instr.h
@@ -0,0 +1,40 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: instr.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+/*
+ * TODO:
+ * Add or modify the struct and other definitions for Poulsbo
+ */
+#ifndef _INSTR_TNC_H
+#define _INSTR_TNC_H
+
+#include<plb/instr.h>
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/mi.h b/drivers/gpu/drm/emgd/emgd/include/tnc/mi.h
new file mode 100644
index 0000000..2bb8c23
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/mi.h
@@ -0,0 +1,41 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: mi.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is a header file for the Intel GFX commands.
+ *  This includes commands specific to Intel hardware and structures specific
+ *  to Intel hardware.  All other commands and structures are available
+ *  through GFX.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _TNC_MI_H
+#define _TNC_MI_H
+
+#include<plb/mi.h>
+
+
+#endif /* _MI_H */
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/regs.h b/drivers/gpu/drm/emgd/emgd/include/tnc/regs.h
new file mode 100644
index 0000000..218722c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/regs.h
@@ -0,0 +1,889 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: regs.h
+ * $Revision: 1.16 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the register definition file for the Atom E6xx platform. This should
+ *  contain device dependent register definitions. Standard register
+ *  definitions (VGA, PCI, etc) should not be put in this file. For those
+ *  see pci.h or vga.h.
+ *-----------------------------------------------------------------------------
+ */
+
+/*
+ * Note: Use _REGS_H_  instead of _TNC_REGS_H_ to insure that no file can
+ * include 2 device dependent register files.
+ */
+#ifndef _REGS_H_
+#define _REGS_H_
+
+#include <pci.h>
+#include <psb_regs.h>
+#include <msvdx.h>
+#include <topaz.h>
+
+/*-----------------------------------------------------------------------------
+ * PCI Register Definitions
+ *---------------------------------------------------------------------------*/
+#define TNC_PCI_MMADR      PCI_BAR_0
+#define TNC_PCI_IOBAR      PCI_BAR_1
+#define TNC_PCI_GMADR      PCI_BAR_2
+#define TNC_PCI_GTTADR     PCI_BAR_3
+
+/*
+ * GVD.MGGC
+ * Device: 2 Offset:50h
+ * [22:20] Graphics mode select
+ * [17] VGA Disable
+ */
+#define TNC_PCI_GC         0x52
+#define TNC_PCI_BSM        0x5C
+
+/* Atom E6xx Device 31 GPIO base address offset */
+#define TNC_PCI_GBA			0x44
+
+#define TNC_D2_MMIO_SIZE  (1024*1024)
+#define TNC_D3_MMIO_SIZE  (512*1024)
+#define TNC_ST_SDVO_MMIO_SIZE  (10*1024)
+
+#define TNC_GTT_SIZE   (128*1024)
+
+
+
+/*-----------------------------------------------------------------------------
+ * General VGA Register Definitions
+ *---------------------------------------------------------------------------*/
+#define FEATURE_CONT_REG      0x3DA  /* Feature Control Register */
+#define FEATURE_CONT_REG_MONO 0x3BA  /* Feature Control Register (Mono) */
+#define FEATURE_CONT_REG_READ 0x3CA  /* Feature Control Register (Read) */
+#define MSR_PORT              0x3C2  /* Miscellaneous Output Port */
+#define MSR_PORT_LSB          0xC2   /* Miscellaneous Output Port LSB */
+#define MSR_READ_PORT         0x3CC  /* Miscellaneous Output Reg (Read) */
+#define STATUS_REG_00         0x3C2  /* Input Status Register 0 */
+#define STATUS_REG_01         0x3DA  /* Input Status Register 1 */
+#define STATUS_REG_01_MONO    0x3BA  /* Input Status Register 1 (Mono) */
+
+/* DAC Register Definitions. */
+#define DAC_PEL_MASK          0x3C6  /* Color Palette Pixel Mask Register */
+#define DAC_READ_INDEX        0x3C7  /* Color Palette Read-Mode Index Reg */
+#define DAC_STATE             0x3C7  /* Color Palette State Register */
+#define DAC_WRITE_INDEX       0x3C8  /* Color Palette Index Register */
+#define DAC_DATA_REG          0x3C9  /* Color Palette Data Register */
+
+
+/*-----------------------------------------------------------------------------
+ * Attribute Controller Register Definitions
+ *---------------------------------------------------------------------------*/
+#define AR_PORT_LSB  0xC0  /*Attribute Controller Index Port LSB */
+
+#define AR00  0x00  /* Color Data Register */
+#define AR01  0x01	/* Color Data Register */
+#define AR02  0x02	/* Color Data Register */
+#define AR03  0x03	/* Color Data Register */
+#define AR04  0x04	/* Color Data Register */
+#define AR05  0x05	/* Color Data Register */
+#define AR06  0x06	/* Color Data Register */
+#define AR07  0x07	/* Color Data Register */
+#define AR08  0x08	/* Color Data Register */
+#define AR09  0x09	/* Color Data Register */
+#define AR0A  0x0A	/* Color Data Register */
+#define AR0B  0x0B	/* Color Data Register */
+#define AR0C  0x0C	/* Color Data Register */
+#define AR0D  0x0D	/* Color Data Register */
+#define AR0E  0x0E	/* Color Data Register */
+#define AR0F  0x0F	/* Color Data Register */
+#define AR10  0x10	/* Mode Control Register */
+#define AR11  0x11	/* Overscan Color Register */
+#define AR12  0x12	/* Color Plane Enable Register */
+#define AR13  0x13	/* Horizontal Pixel Panning Register */
+#define AR14  0x14	/* Pixel Pad Register */
+
+
+/*-----------------------------------------------------------------------------
+ * CRT Controller Register Definitions
+ *---------------------------------------------------------------------------*/
+#define CR_PORT_LSB     0xD4  /* CRT Controller Index Port LSB */
+#define CRT_3D4	        0x3D4 /* Color CRTC Index Port */
+#define CRT_3B4	        0x3B4 /* Monochrome CRTC Index Port */
+
+#define CR00            0x00  /* Horizontal Total Register */
+#define CR01            0x01  /* Horizontal Display Enable End Reg */
+#define CR02            0x02  /* Horizontal Blank Start Register */
+#define CR03            0x03  /* Horizontal Blank End Register */
+#define CR04            0x04  /* Horizontal Sync Start Register */
+#define CR05            0x05  /* Horizontal Sync End Register */
+#define CR06            0x06  /* Vertical Total Register */
+#define CR07            0x07  /* Overflow Register */
+#define CR08            0x08  /* Preset Row Scan Register */
+#define CR09            0x09  /* Maximum Scan Line Register */
+#define DOUBLE_SCANLINE	BIT7  /* Double scan ( 1 = Enable ) */
+#define LCOMP_BIT9      BIT6  /* Bit 9 of line compare register */
+#define VBLANK_BIT9     BIT5  /* Bit 9 of vertical blank start */
+#define CR0A            0x0A  /* Cursor Start Scan Line Register */
+#define CR0B            0x0B  /* Cursor End Scan Line Register */
+#define CR0C            0x0C  /* Start Address High Register */
+#define CR0D            0x0D  /* Start Address Low Register */
+#define CR0E            0x0E  /* Cursor Location High Register */
+#define CR0F            0x0F  /* Cursor Location Low Register */
+#define CR10            0x10  /* Vertical Sync Start Register */
+#define CR11            0x11  /* Vertical Sync End Register */
+#define CR12            0x12  /* Vertical Display Enable End Reg */
+#define CR13            0x13  /* Offset Register */
+#define CR14            0x14  /* Underline Row Register */
+#define CR15            0x15  /* Vertical Blank Start Register */
+#define CR16            0x16  /* Vertical Blank End Register */
+#define CR17            0x17  /* CRT Mode Control Register */
+#define CR18            0x18  /* Line Compare Register */
+#define CR22            0x22  /* Memory Data Latches Register */
+#define CR24            0x24  /* Attribute Controller Toggle Reg */
+
+
+/*-----------------------------------------------------------------------------
+ * Graphics Controller Register Definitions
+ *---------------------------------------------------------------------------*/
+#define GR_PORT_LSB    0xCE   /* Graphics Controller Index Port LSB */
+
+#define GR00           0x00   /* Set/Reset Register */
+#define GR01           0x01   /* Enable Set/Reset Register */
+#define GR02           0x02   /* Color Compare Register */
+#define GR03           0x03   /* Data Rotate Register */
+#define GR04           0x04   /* Read Map Select Register */
+#define GR05           0x05   /* Graphics Mode Register */
+#define GR06           0x06   /* Micsellaneous Register */
+#define RANGE_MAP_MASK BIT3 + BIT2  /* Address range to map mask */
+#define A0_BF_RANGE    000h   /* Map to A0000h-BFFFFh range */
+#define GRAF_MODE      BIT0   /* 1 = Grahics mode, 0 = Text mode */
+#define GR07           0x07   /* Color Don't Care Register */
+#define GR08           0x08   /* Bit Mask Register */
+#define GR10           0x10   /* Address Mapping */
+#define PAGING_TARGET  BIT2 + BIT1 /* 00 = Local/Stolen, 01 = Mem mapped regs */
+#define PAGE_MODE      BIT0   /* Page Map allow access to all FB mem */
+#define GR11           0x11   /* Page Selector */
+#define	GR18           0x18   /* Software Flag */
+
+
+/*-----------------------------------------------------------------------------
+ * Sequencer Register Definitions
+ *---------------------------------------------------------------------------*/
+#define SR_PORT_DATA      0x3C5 /* Sequencer Data Port */
+#define SR_PORT_LSB       0xC4  /* Sequencer Index Port LSB */
+
+#define SR00              0x00  /* Reset Register */
+#define SR01              0x01  /* Clocking Mode Register */
+#define DOT_CLOCK_DIVIDE  BIT3	/* Divide pixel clock by 2 */
+#define SR02              0x02  /* Plane/Map Mask Register */
+#define SR03              0x03  /* Character Font Register */
+#define SR04              0x04  /* Memory Mode Register */
+#define SR07              0x07  /* Horizontal Character Counter Reset */
+
+/*-----------------------------------------------------------------------------
+ * Platform specific PCI Config Register
+ *---------------------------------------------------------------------------*/
+#define TNC_OFFSET_VGA_MSAC         0x62
+
+/* FIXME: Core Clock should be obtained from the Message Control Register*/
+#define INTEL_OFFSET_VGA_CORECLK    0xF0
+
+/* #define INTEL_OFFSET_BRIDGE_CAPREG  0xE0 Not needed for Atom E6xx */
+
+#define PCI_GMS_MASK      BIT6 + BIT5 + BIT4 /* GFX Mode Select Bits Mask */
+#define PCI_LOCAL		  BIT4 /* Local memory enabled */
+#define PCI_DVMT_512K     BIT5 /* 512KB DVMT */
+#define PCI_DVMT_1M       BIT5 + BIT4 /* 1MB DVMT */
+#define PCI_DVMT_8M       BIT6 /* 8MB DVMT */
+
+#define PCI_DRB_REG       0x60 /* DRAM row boundary Register */
+#define PCI_DRC_REG       0x7C /* DRAM Controller Mode Register */
+#define PCI_DT_MASK       BIT0 + BIT1  /* Select SDRAM types.
+                                        *  = 00:  Single data rate SDRAM
+                                        *  = 01:  Dual data rate SDRAM
+                                        *  = Other:  Reserved
+                                        */
+#define DT_SDR_SDRAM      00   /* Single data rate SDRAM */
+#define DT_DDR_SDRAM      01   /* Dual data rate SDRAM */
+
+#define PCI_ESMRAMC_REG   0x91 /* Extended System Management RAM Reg */
+#define PCI_TSEG_SZ		  BIT1 /* TSEG size bit */
+#define PCI_TSEG_512K	  0    /* 512K TSEG */
+#define PCI_TSEG_1M       BIT1 /* 1MB TSEG */
+
+#define PCI_GCLKIO_REG    0xC0 /* GMCH Clock and IO Control Register */
+#define PCI_AGP_Bit       BIT9 /* AGP/DVO Mux Select:
+								*  = 0, DVO/ZV
+								*  = 1, AGP
+								*/
+#define PCI_GMCHCFG_REG   0xC6 /* GMCH Configuration Register */
+#define PCI_SMFREQ_MASK   BIT10 + BIT11
+						   /* System Mem Frequency Select
+                            * = 00:  Intel Reserved
+                            * = 01:  System Memory Frequency is 166Mhz (DDR333) - Intel Reserved
+                            * = 10:  System Memory Frequency is 133Mhz (SDR133, DDR266)
+                            * = 11:  System Memory Frequency is 100Mhz (DDR200)
+                            */
+#define SYS_MEM_FREQ_166  1  /* System Memory Frequency is 166Mhz */
+#define SYS_MEM_FREQ_133  2  /* System Memory Frequency is 133Mhz */
+#define SYS_MEM_FREQ_100  3  /* System Memory Frequency is 100Mhz */
+#define PCI_SMFREQ_POS    10 /* System Memory Frequency position  */
+
+#define PCI_CONFIG_LMINT  0xE0
+#define PREALLOCATED_SIZE (8 * 1024 * 1024)
+
+
+/*-----------------------------------------------------------------------------
+ * General VGA Register Definitions
+ *---------------------------------------------------------------------------*/
+#define FEATURE_CONT_REG      0x3DA  /* Feature Control Register */
+#define FEATURE_CONT_REG_MONO 0x3BA  /* Feature Control Register (Mono) */
+#define FEATURE_CONT_REG_READ 0x3CA  /* Feature Control Register (Read) */
+#define MSR_PORT              0x3C2  /* Miscellaneous Output Port */
+#define MSR_PORT_LSB          0xC2   /* Miscellaneous Output Port LSB */
+#define MSR_READ_PORT         0x3CC  /* Miscellaneous Output Reg (Read) */
+#define STATUS_REG_00         0x3C2  /* Input Status Register 0 */
+#define STATUS_REG_01         0x3DA  /* Input Status Register 1 */
+#define STATUS_REG_01_MONO    0x3BA  /* Input Status Register 1 (Mono) */
+
+/* DAC Register Definitions. */
+#define DAC_PEL_MASK          0x3C6  /* Color Palette Pixel Mask Register */
+#define DAC_READ_INDEX        0x3C7  /* Color Palette Read-Mode Index Reg */
+#define DAC_STATE             0x3C7  /* Color Palette State Register */
+#define DAC_WRITE_INDEX       0x3C8  /* Color Palette Index Register */
+#define DAC_DATA_REG          0x3C9  /* Color Palette Data Register */
+
+
+/*-----------------------------------------------------------------------------
+ * Memory mapped I/O Registers Definitions
+ *---------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------
+ * Instruction and Interrupt Control Registers (01000h - 02FFFh)
+ *---------------------------------------------------------------------------*/
+#define PGTBL_CTL         0x02020  /* Page Table Control Register */
+#define HWS_PGA           0x02080  /* Hardware Status Page Address register */
+#define HWSTAM            0x02098  /* Hardware Status Mask */
+#define SCPD0             0x0209C  /* Scratch Pad 0 (Debug) */
+#define IER               0x020A0  /* Interrupt Enable */
+#define IIR               0x020A4  /* Interrupt Identity */
+#define IMR               0x020A8  /* Interrupt Mask */
+#define ISR               0x020AC  /* Interrupt Status */
+#define EIR               0x020B0  /* Error Identity */
+#define EMR               0x020B4  /* Error Mask */
+#define ESR               0x020B8  /* Error Status */
+#define FW_BLC_SELF       0x020E0  /* Display FIFO Watermark */
+#define MI_ARB_STATE      0x020E4  /* Memory Interface Arbitration State */
+#define G_DEBUG		  0x020FC  /* G-UNIT Debug enable register */
+
+#if 0
+/*-----------------------------------------------------------------------------
+ * FENCE and Per Process GTT Control Registers (02000h - 031FFh)
+ * --------------------------------------------------------------------------*/
+#define FENCE0            0x02000 /* Fence table registers */
+#define FENCE1            0x02004
+#define FENCE2            0x02008
+#define FENCE3            0x0200C
+#define FENCE4            0x02010
+#define FENCE5            0x02014
+#define FENCE6            0x02018
+#define FENCE7            0x0201C
+#define FENCE8            0x03000
+#define FENCE9            0x03004
+#define FENCE10           0x03008
+#define FENCE11           0x0300C
+#define FENCE12           0x03010
+#define FENCE13           0x03014
+#define FENCE14           0x03018
+#define FENCE15           0x0301C
+#endif
+/*-----------------------------------------------------------------------------
+ * FIXME: For TNC, we were not able to find specs detailing the FENCE registers
+ * Use the GN4 FENCE Registers for the time being as a placeholder till we can
+ * nail down the FENCE registers
+ * --------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------------
+ * FENCE and Per Process GTT Control Registers (03000h - 031FFh)
+ *
+ * The FENCE registers are now 64-bits but we can only read/write 32-bits
+ * at a time.  As a result, each register has aliases for the whole 64-bits,
+ * the low DWORD, and the high DWORD.
+ *
+ * This is important for restoring the registers, since we must always write
+ * the high DWORD first.
+ * --------------------------------------------------------------------------*/
+#define FENCE0            0x03000 /* Fence table registers */
+#define FENCE0l           0x03000
+#define FENCE0h           0x03004
+#define FENCE1            0x03008
+#define FENCE1l           0x03008
+#define FENCE1h           0x0300C
+#define FENCE2            0x03010
+#define FENCE2l           0x03010
+#define FENCE2h           0x03014
+#define FENCE3            0x03018
+#define FENCE3l           0x03018
+#define FENCE3h           0x0301C
+#define FENCE4            0x03020
+#define FENCE4l           0x03020
+#define FENCE4h           0x03024
+#define FENCE5            0x03028
+#define FENCE5l           0x03028
+#define FENCE5h           0x0302C
+#define FENCE6            0x03030
+#define FENCE6l           0x03030
+#define FENCE6h           0x03034
+#define FENCE7            0x03038
+#define FENCE7l           0x03038
+#define FENCE7h           0x0303C
+#define FENCE8            0x03040
+#define FENCE8l           0x03040
+#define FENCE8h           0x03044
+#define FENCE9            0x03048
+#define FENCE9l           0x03048
+#define FENCE9h           0x0304C
+#define FENCE10           0x03050
+#define FENCE10l          0x03050
+#define FENCE10h          0x03054
+#define FENCE11           0x03058
+#define FENCE11l          0x03058
+#define FENCE11h          0x0305C
+#define FENCE12           0x03060
+#define FENCE12l          0x03060
+#define FENCE12h          0x03064
+#define FENCE13           0x03068
+#define FENCE13l          0x03068
+#define FENCE13h          0x0306C
+#define FENCE14           0x03070
+#define FENCE14l          0x03070
+#define FENCE14h          0x03074
+#define FENCE15           0x03078
+#define FENCE15l          0x03078
+#define FENCE15h          0x0307C
+
+/*-----------------------------------------------------------------------------
+ * MISC I/0 Contol Register ( 05000h - 05FFFh )
+ *---------------------------------------------------------------------------*/
+#define IO_OFF          0x05000         /* Register group offset */
+
+#define IO00            0x05000         /* Hsync / Vsync control register */
+#define GPIO0           0x05010         /* GPIO register 0 (DDC1) */
+#define	DDC1_SCL_PIN    GPIO0_SCL_PIN   /* DDC1 SCL GPIO pin # */
+#define	DDC1_SDA_PIN    GPIO0_SDA_PIN   /* DDC1 SDA CPIO pin # */
+#define GPIO1           0x05014         /* GPIO register 1 (I2C) */
+#define	I2C_SCL_PIN     GPIO1_SCL_PIN   /* I2C SCL GPIO pin # */
+#define	I2C_SDA_PIN     GPIO1_SDA_PIN   /* I2C SDA CPIO pin # */
+#define GPIO2           0x05018         /* GPIO register 2 (DDC2) */
+#define	DDC2_SCL_PIN    GPIO2_SCL_PIN   /* DDC2 SCL GPIO pin # */
+#define	DDC2_SDA_PIN    GPIO2_SDA_PIN   /* DDC2 SDA CPIO pin # */
+#define GPIO3           0x0501C         /* GPIO register 3 (AGP mux DVI DDC) */
+#define GPIO4           0x05020         /* GPIO register 4 (AGP mux I2C) */
+#define GPIO5           0x05024         /* GPIO register 5 (AGP mux DDC2/I2C) */
+
+#define GPIOPIN0        GPIO0
+#define GPIOPIN1        GPIO0+1
+#define GPIOPIN2        GPIO1
+#define GPIOPIN3        GPIO1+1
+#define GPIOPIN4        GPIO2
+#define GPIOPIN5        GPIO2+1
+#define GPIOPIN6        GPIO3
+#define GPIOPIN7        GPIO3+1
+#define GPIOPIN8        GPIO4
+#define GPIOPIN9        GPIO4+1
+#define GPIOPIN10       GPIO5
+#define GPIOPIN11       GPIO5+1
+#define GPIOPINMAX      12
+
+#define GMBUS0          0x5100 /* GMBUS clock/device select register */
+#define GMBUS1          0x5104 /* GMBUS command/status register */
+#define GMBUS2          0x5108 /* GMBUS status register */
+#define GMBUS3          0x510c /* GMBUS data buffer register */
+#define GMBUS4          0x5110 /* GMBUS REQUEST_INUSE register */
+#define GMBUS5          0x5120 /* GMBUS 2-Byte Index register */
+#define GMBUS6          0x5124 /* GMBUS Clock divider */
+
+/*  GMBUS1 Bits */
+#define SW_CLR_INT      BIT31
+#define SW_RDY          BIT30
+#define ENT             BIT29
+#define STO             BIT27
+#define ENIDX           BIT26
+#define STA             BIT25
+
+/*  GMBUS2 Bits */
+#define INUSE           BIT15
+#define HW_WAIT         BIT14
+#define HW_TMOUT        BIT13
+#define HW_INT          BIT12
+#define HW_RDY          BIT11
+#define HW_BUS_ERR      BIT10
+#define GA              BIT9
+
+/*-----------------------------------------------------------------------------
+ * Clock Control and PM Register ( 06000h - 06FFFh )
+ *---------------------------------------------------------------------------*/
+#define VGA0_DIVISOR    0x06000  /* VGA 0  Divisor */
+#define VGA1_DIVISOR    0x06004  /* VGA 1 Divisor */
+#define VGA_PD          0x06010  /* VGA Post Divisor Select */
+#define DPLLAMD         0x0601C  /* Display PLL A SDVO Multiplier/Divisor */
+#define DPLLBMD         0x06020  /* Display PLL B SDVO Multiplier/Divisor */
+
+/*-----------------------------------------------------------------------------
+ * DPLL A Control Register ( 0F000h - 0FFFFh )
+ *---------------------------------------------------------------------------*/
+#define DPLLACNTR       0x0F014  /* Display PLL A Control */
+#define FPA0            0x0F040  /* DPLL A Divisor 0 */
+#define FPA1            0x0F044  /* DPLL A Divisor 1 */
+#define DPLL_TEST		0x0F06C  /* DPLLA Test Register */
+
+/*-----------------------------------------------------------------------------
+ * DPLL B Control Register ( 06000h - 06FFFh )
+ *---------------------------------------------------------------------------*/
+#define DPLLBCNTR       0x06018  /* Display PLL B Control */
+#define FPB0            0x06048  /* DPLL B Divisor 0 */
+#define FPB1            0x0604C  /* DPLL B Divisor 1 */
+#define TNC_DPLL_TEST	0x0606C	 /* DPLL A and DPLL B test register */
+
+#define DREFCLK         0x0
+#define TVCLKINBC       0x4000
+#define CLOCK_2X        0x40000000
+
+#define P2D_CG_DIS      0x06200  /* Clock Gating Disable */
+/* Not available in Atom E6xx */
+/* #define P3D_CG_DIS      0x06204 */ /* Clock Gating Disable */
+
+
+/*-----------------------------------------------------------------------------
+ * Display Palette Register Definitions (0A000h - 0AFFFh)
+ *---------------------------------------------------------------------------*/
+#define DPALETTE_A      0x0A000  /* Display Pipe A Palette */
+#define DPALETTE_B      0x0A800  /* Display Pipe B Palette */
+
+
+/*-----------------------------------------------------------------------------
+ * Display Pipeline / Port Register Definitions (60000h - 6FFFFh)
+ *---------------------------------------------------------------------------*/
+#define DP_OFFSET       0x60000  /* register group offset */
+#define PIPEA_TIMINGS   0x60000
+#define HTOTAL_A        0x60000  /* Pipe A Horizontal Total Register */
+#define ACTIVE_DISPLAY  0x7FF    /* bit [ 10:0 ] */
+#define HBLANK_A        0x60004  /* Pipe A Horizontal Blank Register */
+#define HSYNC_A         0x60008  /* Pipe A Horizontal Sync Register */
+#define VTOTAL_A        0x6000C  /* Pipe A Vertical Total Register */
+#define VBLANK_A        0x60010  /* Pipe A Vertical Blank Register */
+#define VSYNC_A         0x60014  /* Pipe A Vertical Sync Register */
+#define PIPEASRC        0x6001C  /* Pipe A Source Image Size Register */
+#define BCLRPAT_A       0x60020  /* Pipe A Border Color Pattern Register */
+#define CRCCTRLREDA     0x60050  /* Pipe A CRC Red Control Register */
+#define CRCCTRLGREENA   0x60054  /* Pipe A CRC Green Control Register */
+#define CRCCTRLBLUEA    0x60058  /* Pipe A CRC Blue Control Register */
+#define CRCCTRLRESA     0x6005C  /* Pipe A CRC Alpha Control Register */
+
+/*-----------------------------------------------------------------------------
+ * Pipe B registers are shared between Device 2 and Device 3
+ * Atom E6xx silicon design specifies that both device 2 and device 3
+ * Pipe B registers need to be set sequencially. Device 2, followed by
+ * Device 3
+ *---------------------------------------------------------------------------*/
+#define PIPEB_TIMINGS   0x61000
+#define HTOTAL_B        0x61000  /* Pipe B Horizontal Total Register */
+#define HBLANK_B        0x61004  /* Pipe B Horizontal Blank Register */
+#define HSYNC_B         0x61008  /* Pipe B Horizontal Sync Register */
+#define VTOTAL_B        0x6100C  /* Pipe B Vertical Total Register */
+#define VBLANK_B        0x61010  /* Pipe B Vertical Blank Register */
+#define VSYNC_B         0x61014  /* Pipe B Vertical Sync Register */
+#define PIPEBSRC        0x6101C  /* Pipe B Source Image Size Register */
+#define BCLRPAT_B       0x61020  /* Pipe B Border Color Pattern Register */
+#define VSYNCSHIFT_B	0x61028  /* Pipe B Vertical Sync Shift Register */
+#define CRCCTRLREDB     0x61050  /* Pipe B CRC Red Control Register */
+#define CRCCTRLGREENB   0x61054  /* Pipe B CRC Green Control Register */
+#define CRCCTRLBLUEB    0x61058  /* Pipe B CRC Blue Control Register */
+#define CRCCTRLRESB     0x6105C  /* Pipe B CRC Alpha Control Register */
+
+/* These registers are in Device 3 */
+#define PORT_HPLUG_EN		0x61110  /* Port Hot Plug Enable */
+#define PORT_HPLUG_STAT 	0x61114  /* Port Hot Plug Status */
+#define SDVOBCNTR       	0x61140  /* Digital Display Port B Control */
+#define LVDSCNTR        	0x61180  /* Digital Display Port Control */
+#define SDVO_BUFF_CTRL_REG	0x61170  /* SDVO Buffer Control */
+
+/* Panel Power Sequencing */
+#define LVDS_PNL_PWR_STS  0x61200  /* LVDS Panel Power Status Register */
+#define LVDS_PNL_PWR_CTL  0x61204  /* LVDS Panel Power Control Register */
+#define PP_ON_DELAYS      0x61208  /* Panel Power On Sequencing Delays */
+#define PP_OFF_DELAYS     0x6120C  /* Panel Power Off Sequencing Delays */
+#define PP_DIVISOR        0x61210  /* Panel Power Cycle Delay and Reference */
+
+/* Panel Fitting */
+#define PFIT_CONTROL      0x61230  /* Panel Fitting Control */
+#define PFIT_PGM_RATIOS   0x61234  /* Programmed Panel Fitting Ratios */
+
+/* Backlight control */
+#define BLC_PWM_CTL2      0x61250  /* Backlight PWM Control 2 */
+#define BLC_PWM_CTL       0x61254  /* Backlight PWM Control */
+#define BLM_HIST_CTL      0x61260  /* Image BLM Histogram Control */
+
+#define PORT_EN           BIT31
+#define PORT_PIPE_SEL     BIT30
+#define PORT_PIPE_SEL_POS 30
+#define PORT_PIPE_A       0      /* 0 = Pipe A */
+#define PORT_PIPE_B       BIT30  /* 1 = Pipe B */
+#define STALL_MASK        BIT29 + BIT28
+#define STALL_ENABLE      BIT28
+#define SYNC_MASK         BIT15 + BIT11 + BIT10 + BIT4 + BIT3
+#define SYNC_POLARITY     BIT15  /* 1 = Use VGA register */
+#define VSYNC_OUTPUT      BIT11
+#define HSYNC_OUTPUT      BIT10
+#define VSYNC_POLARITY    BIT4
+#define HSYNC_POLARITY    BIT3
+#define FP_DATA_ORDER     BIT14
+#define SUBDATA_ORDER     BIT6
+#define BORDER_EN         BIT7
+#define DISPLAY_EN        BIT2
+#define INTERLACED_BIT    0x00100000
+#define RGBA_BITS         0x00030000
+
+
+
+/*-----------------------------------------------------------------------------
+ * Display Pipeline A Register ( 70000h - 70024h )
+ *---------------------------------------------------------------------------*/
+#define PIPEA_SCANLINE_COUNT   0x70000  /* Pipe A Scan Line Count (RO) */
+#define PIPEA_SCANLINE_COMPARE 0x70004  /* Pipe A SLC Range Compare (RO) */
+#define PIPEA_CONF             0x70008  /* Pipe A Configuration */
+#define PIPE_STATUS_OFFSET     0x1C
+#define PIPEAGCMAXRED          0x70010  /* Pipe A Gamma Correct. Max Red */
+#define PIPEAGCMAXGRN          0x70014  /* Pipe A Gamma Correct. Max Green */
+#define PIPEAGCMAXBLU          0x70018  /* Pipe A Gamma Correct. Max Blue */
+#define PIPEA_STAT             0x70024  /* Pipe A Display Status */
+#define PIPEA_DISP_ARB_CTRL    0x70030  /* Display Arbitration Control */
+#define FW_1                   0x70034
+#define FW_2                   0x70038
+#define FW_3                   0x7003C
+#define PIPEA_FRAME_HIGH       0x70040  /* Pipe A Frame Count High */
+#define PIPEA_FRAME_PIXEL      0x70044  /* Pipe A Frame Cnt Low & pixel count */
+#define FW_4                   0x70050
+#define FW_5                   0x70054
+#define FW_6                   0x70058
+
+#define PIPE_PIXEL_MASK        0x00ffffff
+#define PIPE_FRAME_HIGH_MASK   0x0000ffff
+#define PIPE_FRAME_LOW_MASK    0xff000000
+#define PIPE_FRAME_LOW_SHIFT   24
+
+
+/*-----------------------------------------------------------------------------
+ * Display Pipeline B Register ( 71000h - 71024h )
+ *---------------------------------------------------------------------------*/
+#define PIPEB_SCANLINE_COUNT   0x71000 /* Pipe B Disp Scan Line Count Reg */
+#define PIPEB_SCANLINE_COMPARE 0x71004 /* Pipe B Disp Scan Line Cnt Range Cmp */
+#define PIPEB_CONF             0x71008 /* Pipe B Pixel Pipeline Config Reg */
+#define PIPEBGCMAXRED          0x71010 /* Pipe B Gamma Correct. Max Red */
+#define PIPEBGCMAXGRN          0x71014 /* Pipe B Gamma Correct. Max Green */
+#define PIPEBGCMAXBLU          0x71018 /* Pipe B Gamma Correct. Max Blue */
+#define PIPEB_STAT             0x71024 /* Display Status Select Register */
+#define PROG_STALL             0x6102C /* Programmable cDVO Stall Register */
+#define PIPEB_FRAME_HIGH       0x71040 /* Pipe B Frame Count High */
+#define PIPEB_FRAME_PIXEL      0x71044 /* Pipe B Frame Cnt Low and pixel cnt */
+
+
+#define VBLANK_EVN_STS_EN   BIT20
+#define VBLANK_ODD_STS_EN   BIT21
+#define VBLANK_EVN_STS      BIT4
+#define VBLANK_ODD_STS      BIT5
+
+
+/* following bit flag defs can be re-used for Pipe-B */
+#define PIPE_ENABLE       BIT31
+#define PIPE_LOCK         BIT29
+#define GAMMA_MODE        BIT24
+#define HOT_PLUG_EN       BIT26
+/* Setting this bit to a 1 in the PIPE{A|B}_STAT register, enables the
+ * consideration of vertical sync interrupts.
+ */
+#define VSYNC_STS_EN      BIT25
+#define INTERLACE_EN	  BIT23|BIT22
+/* Setting this bit to a 1 in the PIPE{A|B}_STAT register, enables the
+ * consideration of vertical blank interrupts.
+ */
+#define VBLANK_STS_EN     BIT17
+#define HOT_PLUG_STS      BIT10
+#define VSYNC_STS         BIT9
+#define VBLANK_STS        BIT1
+/* The following are "sticky" status bits in the PIPE{A|B}_STAT register.  They
+ * are cleared by writing a 1 to them.  Theres is code that reads a
+ * PIPE{A|B}_STAT register into a variable, then modifies the variable, and
+ * writes it back to the register.  These bits should be treated specially, so
+ * as not to inadvertantly clear the status bits, so that other code looking
+ * for those bits to be set won't miss it.
+ */
+#define PIPESTAT_STS_BITS ((unsigned long) BIT31 | BIT13 | BIT12 | BIT11 | \
+	VSYNC_STS | BIT8 | BIT5 | BIT4 | VBLANK_STS | BIT0)
+
+/*-----------------------------------------------------------------------------
+ * cDVO Registers
+ * --------------------------------------------------------------------------*/
+#define CDVO_CTRL	  0x07000  /* cDVO Control Register */
+#define CDVO_SLEW_RATE	  0x07004  /* cDVO Slew Rate Register */
+#define CDVO_STRENGTH	  0x07008  /* cDVO Strength Register */
+#define CDVO_RCOMP_UPDATE 0x0700C  /* cDVO RCOMP update Register */
+
+/*-----------------------------------------------------------------------------
+ * TNC_SDVOFAM Registers
+ * --------------------------------------------------------------------------*/
+#define DPLL_ANACORE_CTRL 	  0x06300
+#define DPLL_MISC	  	  0x06304
+#define DPLL_MONITOR	  	  0x06308
+#define DPLL_MONITOR2	  	  0x0630C
+#define DPLL_TEST_COMPARATOR      0x06310
+#define SDVOB_TX_LSKEW	          0x06314
+
+/*-----------------------------------------------------------------------------
+ * Hardware Cursor Register Definitions (70080h - 7009Ch)
+ *---------------------------------------------------------------------------*/
+#define CUR_A_CNTR        0x70080  /*Cursor A Control */
+#define CUR_B_CNTR        0x700C0
+#define CUR_BASE_OFFSET   0x4
+#define CUR_POS_OFFSET    0x8
+#define CUR_PAL0_OFFSET   0x10
+#define CUR_PAL1_OFFSET   0x14
+#define CUR_PAL2_OFFSET   0x18
+#define CUR_PAL3_OFFSET   0x1C
+
+/* Define these for ease of reference */
+#define CURSOR_A_BASE     CUR_A_CNTR + CUR_BASE_OFFSET
+#define CURSOR_A_POS      CUR_A_CNTR + CUR_POS_OFFSET
+#define CURSOR_A_PAL0     CUR_A_CNTR + CUR_PAL0_OFFSET
+#define CURSOR_A_PAL1     CUR_A_CNTR + CUR_PAL1_OFFSET
+#define CURSOR_A_PAL2     CUR_A_CNTR + CUR_PAL2_OFFSET
+#define CURSOR_A_PAL3     CUR_A_CNTR + CUR_PAL3_OFFSET
+#define CURSOR_B_BASE     CUR_B_CNTR + CUR_BASE_OFFSET
+#define CURSOR_B_POS      CUR_B_CNTR + CUR_POS_OFFSET
+#define CURSOR_B_PAL0     CUR_B_CNTR + CUR_PAL0_OFFSET
+#define CURSOR_B_PAL1     CUR_B_CNTR + CUR_PAL1_OFFSET
+#define CURSOR_B_PAL2     CUR_B_CNTR + CUR_PAL2_OFFSET
+#define CURSOR_B_PAL3     CUR_B_CNTR + CUR_PAL3_OFFSET
+
+/*-----------------------------------------------------------------------------
+ * Display Plane A Register Definitions (70180h - 70188h)
+ *---------------------------------------------------------------------------*/
+#define DSPAAFLIP    	0x7017C
+#define DSPACNTR        0x70180  /* Display Plane A */
+#define DSPALINOFF      0x70184  /* Display A Linear Offset */
+#define DSPASTRIDE      0x70188  /* Display A Stride */
+#define DSPAKEYVAL      0x70194  /* Sprite color key value */
+#define DSPAKEYMASK     0x70198  /* Sprite color key mask */
+#define DSPASURF        0x7019C  /* Display A Suface base address */
+#define DSPATILEOFF     0x701A4  /* Display A Tiled Offset */
+
+/*-----------------------------------------------------------------------------
+ * Display Plane B Register Definitions (71180h - 71188h)
+ *---------------------------------------------------------------------------*/
+#define DSPBFLIP        0x7117C  /* Display B Async flip */
+#define DSPBCNTR        0x71180  /* Display Plane B */
+#define DSPBLINOFF      0x71184  /* Display B Linear Offset */
+#define DSPBSTRIDE      0x71188  /* Display B Stride */
+#define DSPBKEYVAL      0x71194  /* Sprite color key value */
+#define DSPBKEYMASK     0x71198  /* Sprite color key mask */
+#define DSPBSURF        0x7119C  /* Display B Suface base address */
+#define DSPBTILEOFF     0x711A4  /* Display B Tiled Offset */
+
+/*-----------------------------------------------------------------------------
+ * Source Format Definition for DSPxCNTR
+ *---------------------------------------------------------------------------*/
+#define DSPxCNTR_ARGB_8888			0x1C000000
+#define DSPxCNTR_RGB_8888			0x18000000
+#define DSPxCNTR_RGB_565			0x14000000
+#define DSPxCNTR_RGB_555			0x10000000
+#define DSPxCNTR_RGB_8				0x08000000
+#define DSPxCNTR_SRC_FMT_MASK			0x3C000000 /*mask for above*/
+
+/*-----------------------------------------------------------------------------
+ * Display Plane C Register Definitions (72180h - 72188h)
+ *---------------------------------------------------------------------------*/
+#define DSPCCNTR        0x72180  /* Display Plane C */
+#define DSPCLINOFF      0x72184  /* Display C Linear Offset */
+#define DSPCSTRIDE      0x72188  /* Display C Stride */
+#define DSPCPOS         0x7218C  /* Display C Position */
+#define DSPCSIZE        0x72190  /* Display C Size */
+#define DSPCKEYMINVAL   0x72194  /* Sprite color key Min */
+#define DSPCKEYMASK     0x72198  /* Sprite color key mask */
+#define DSPCSURF        0x7219C  /* Display C Suface base address */
+#define DSPCKEYMAXVAL   0x721A0  /* Display C Sprint color key Max */
+#define DSPCTILEOFF     0x721A4  /* Display C Tiled Offset */
+#define DSPCCONTALPHA	0x721A8	 /* Display C Constant Alpha */
+
+#define DCLRC0          0x721D0  /* Display C Color Correction 0 */
+#define DCLRC1          0x721D4  /* Display C Color Correction 1 */
+#define DPYC_GAMC5      0x721E0  /* Display C Gamma Correction 5 */
+#define DPYC_GAMC4      0x721E4  /* Display C Gamma Correction 4 */
+#define DPYC_GAMC3      0x721E8  /* Display C Gamma Correction 3 */
+#define DPYC_GAMC2      0x721EC  /* Display C Gamma Correction 2 */
+#define DPYC_GAMC1      0x721F0  /* Display C Gamma Correction 1 */
+#define DPYC_GAMC0      0x721F4  /* Display C Gamma Correction 0 */
+
+#define PLANE_ENABLE    BIT31
+#define GAMMA_ENABLE    BIT30
+#define BPP_MASK        BIT29 + BIT28 + BIT27 + BIT26
+#define BPP_POS         26
+#define STEREO_ENABLE   BIT25
+#define PIPE_SEL        BIT24
+#define PIPE_SEL_POS    24
+#define PIXEL_MULTIPLY  BIT21 + BIT20
+#define STEREO_POLARITY BIT18
+
+/* Common offsets for all Display Pipeline registers */
+#define DSP_LINEAR_OFFSET 0x04  /* Offset from the control reg */
+#define DSP_STRIDE_OFFSET 0x08  /* Offset from the control reg */
+#define DSP_SIZE_OFFSET   0x10  /* Offset from the control reg */
+#define DSP_START_OFFSET  0x1c  /* Offset from the control reg */
+#define DSP_TOFF_OFFSET   0x24  /* Offset from the control reg */
+
+/*-----------------------------------------------------------------------------
+ * VGA Display Plane Control Register Definitions (71400h)
+ *---------------------------------------------------------------------------*/
+#define VP00             0x71400
+#define VGACNTRL         0x71400  /* VGA Display Plane Control Register */
+#define VGA_DOUBLE       BIT30
+#define VGA_PIPE         BIT29
+#define VGA_CENTER_MASK  BIT25 + BIT24
+#define VGA_CENTER_1     BIT25
+#define VGA_CENTER_0     BIT24
+#define VGA_PAL_READ     BIT23
+#define VGA_PAL_MASK     BIT22 + BIT21
+#define VGA_PALA_DISABLE BIT22
+#define VGA_PALB_DISABLE BIT21
+#define DAC_8_BIT	     BIT20
+#define VGA_8_DOT	     BIT18
+
+#define ADD_ID           0x71408  /* ADD Card ID Register*/
+
+/*-----------------------------------------------------------------------------
+ * Overlay Plane Control Register Definitions (30000h)
+ *---------------------------------------------------------------------------*/
+#define OVADD            0x30000  /* Overlay Control */
+
+/*-----------------------------------------------------------------------------
+ * VBIOS Software flags  00h - 0Fh
+ *---------------------------------------------------------------------------*/
+#define DSP_CHICKENBITS	0x70400  /* Chicken Bit */
+#define SWFABASE        0x70410  /* Software flags A Base Addr */
+#define SWF00           0x70410
+#define SWF01           0x70414
+#define SWF02           0x70418
+#define SWF03           0x7041C
+#define SWF04           0x70420
+#define SWF05           0x70424
+#define SWF06           0x70428
+#define SWF07           0x7042C
+#define SWF08           0x70430
+#define SWF09           0x70434
+#define SWF0A           0x70438
+#define SWF0B           0x7043C
+#define SWF0C           0x70440
+#define SWF0D           0x70444
+#define SWF0E           0x70448
+#define SWF0F           0x7044C
+
+/*-----------------------------------------------------------------------------
+ * VBIOS Software flags  10h - 1Fh
+ *---------------------------------------------------------------------------*/
+#define SWFBBASE        0x71410  /* Software flags B Base Addr */
+#define SWF10           0x71410
+#define SWF11           0x71414
+#define SWF12           0x71418
+#define SWF13           0x7141C
+#define SWF14           0x71420
+#define SWF15           0x71424
+#define SWF16           0x71428
+#define SWF17           0x7142C
+#define SWF18           0x71430
+#define SWF19           0x71434
+#define SWF1A           0x71438
+#define SWF1B           0x7143C
+#define SWF1C           0x71440
+#define SWF1D           0x71444
+#define SWF1E           0x71448
+#define SWF1F           0x7144C
+
+#define	SWF30			0x72414
+#define SWF31			0x72418
+#define SWF32			0x7241C
+
+/*-----------------------------------------------------------------------------
+ * Software Flag Registers (71410h - 71428h)
+ *---------------------------------------------------------------------------*/
+/* Map old software flag names to their new Gen4 names */
+#define SF00  SWF10
+#define SF01  SWF11
+#define SF02  SWF12
+#define SF03  SWF13
+#define SF04  SWF14
+#define SF05  SWF15
+#define SF06  SWF16
+
+/*-----------------------------------------------------------------------------
+ * GPIO Control Registers(05000h - 05023h)
+ *---------------------------------------------------------------------------*/
+/* GPIO registers 0x0500 - 0x500C is reserved */
+#define GPIOCTL_1	0x05014
+#define GPIOCTL_2	0x05018
+#define GPIOCTL_4	0x05020
+
+/*-----------------------------------------------------------------------------
+ * Scratch register to be used as additional parameter in SMI
+ *---------------------------------------------------------------------------*/
+#define SCRATCH_SWF6         0x71428
+
+/*-----------------------------------------------------------------------------
+ * Miscellaneous registers
+ ----------------------------------------------------------------------------*/
+#define HW_ST_PAGE_ADDR      0x02080
+
+/*-----------------------------------------------------------------------------
+ * GMBUS : I2C Bus Types
+ ----------------------------------------------------------------------------*/
+//#define GMBUS_ANALOG_DDC    1
+
+//#define GMBUS_INT_LVDS_DDC  2
+#define I2C_INT_LVDS_DDC  2
+
+#define GMBUS_DVO_REG       3
+
+#define GMBUS_DVOB_DDC      4
+//#define GMBUS_DVOC_DDC      5
+
+/*-----------------------------------------------------------------------------
+ * LPC Register Offsets. Used for LVDS GPIO Bit Bashing. Registers are part
+ * Atom E6xx [D31:F0]
+ ----------------------------------------------------------------------------*/
+#define RGEN    0x20
+#define RGIO    0x24
+#define RGLVL   0x28
+#define RGTPE   0x2C
+#define RGTNE   0x30
+#define RGGPE   0x34
+#define RGSMI   0x38
+#define RGTS    0x3C
+
+
+#endif /* _REGS_H_ */
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/sgx.h b/drivers/gpu/drm/emgd/emgd/include/tnc/sgx.h
new file mode 100644
index 0000000..c43d490
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/sgx.h
@@ -0,0 +1,36 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sgx.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  These are the defines specific to the SGX engine code.
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _TNC_SGX_H
+#define _TNC_SGX_H
+
+#include<plb/sgx.h>
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/state3d.h b/drivers/gpu/drm/emgd/emgd/include/tnc/state3d.h
new file mode 100644
index 0000000..b32aea2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/state3d.h
@@ -0,0 +1,43 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: state3d.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file is an inter-module header file for manipulating the 3D
+ *  State variables.
+ *-----------------------------------------------------------------------------
+ */
+/*
+ * This is referenced from Napa code. For Poulsbo, the HW spec may be
+ * different. Be ready for the new change.
+ */
+
+#ifndef _TNC_STATE3D_H
+#define _TNC_STATE3D_H
+
+#include <plb/state3d.h>
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/tnc/state3d_plb.h b/drivers/gpu/drm/emgd/emgd/include/tnc/state3d_plb.h
new file mode 100644
index 0000000..fd5e628
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/tnc/state3d_plb.h
@@ -0,0 +1,38 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: state3d_plb.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file is an inter-module header file for manipulating the 3D
+ *  State variables.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _STATE3D_TNC_H
+#define _STATE3D_TNC_H
+
+#include <plb/state3d_plb.h>
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/include/topaz.h b/drivers/gpu/drm/emgd/emgd/include/topaz.h
new file mode 100755
index 0000000..e14b46c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/topaz.h
@@ -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/drivers/gpu/drm/emgd/emgd/include/utils.h b/drivers/gpu/drm/emgd/emgd/include/utils.h
new file mode 100644
index 0000000..18fe9c3
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/utils.h
@@ -0,0 +1,174 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: utils.h
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _UTILS_H_
+#define _UTILS_H_
+
+#include <config.h>
+#include <igd_mode.h>
+#include <general.h>
+#include <mode.h>
+
+/* Get the MMIO pointer for a display context */
+#define MMIO(dsp) \
+ EMGD_MMIO((((igd_display_context_t *)dsp)->context->device_context.virt_mmadr))
+
+/* Get the 2nd MMIO pointer for a display context */
+#define MMIO_SDVO(dsp) \
+ EMGD_MMIO(((igd_display_context_t *)dsp)->context->device_context.virt_mmadr_sdvo)
+
+/* Get the STMicro SDVO MMIO pointer for a display context */
+#define MMIO_SDVO_ST(dsp) \
+ EMGD_MMIO(((igd_display_context_t *)dsp)->context->device_context.virt_mmadr_sdvo_st)
+#define MMIO_SDVO_ST_GPIO(dsp) \
+ EMGD_MMIO(((igd_display_context_t *)dsp)->context->device_context.virt_mmadr_sdvo_st_gpio)
+
+/* Definition: value = READ_MMIO_REG(igd_display_context_t *, reg) */
+#define READ_MMIO_REG(dsp, reg) \
+	EMGD_READ32( MMIO(dsp) +(reg) )
+
+/* Definition: WRITE_MMIO_REG(igd_display_context_t *, reg, value) */
+#define WRITE_MMIO_REG(dsp, reg, value) \
+	EMGD_WRITE32(value, ( MMIO(dsp) + (reg) ) )
+
+/* Definition:WRITE_MMIO_REG_BITS(igd_display_context_t *, reg, value, mask) */
+#define WRITE_MMIO_REG_BITS(dsp, reg, data, mask) \
+{                                                 \
+	unsigned long tmp;                            \
+	tmp = READ_MMIO_REG((dsp), (reg));            \
+	tmp &= (~(mask));                             \
+	tmp |= ((data) & (mask));                     \
+	WRITE_MMIO_REG((dsp), (reg), (tmp));          \
+}
+
+#define PORT_TYPE(d) (PORT(d, (d->port_number))->port_type)
+#define PORT_TYPE_DH(dh) \
+	(PORT(dh, (((igd_display_context_t *)dh)->port_number))->port_type)
+
+#ifdef CONFIG_TNC
+/* Based on display port determine which mmio base to use:
+ *       port_type == SDVO ==> use 0:3:0 device mmio
+ *       port_type == LVDS ==> use 0:2:0 device mmio
+ *       port_type == LPC  ==> use 0:31:0 device mmio
+ */
+#define MMIO_TNC(port_type) EMGD_MMIO(get_mmio_tnc(port_type))
+
+#define READ_MMIO_REG_TNC(pt, reg) read_mmio_reg_tnc(pt, reg)
+#define WRITE_MMIO_REG_TNC(pt, reg, value) write_mmio_reg_tnc(pt, reg, value)
+
+/* Defined in micro_mode_tnc.c */
+extern unsigned char *get_mmio_tnc(unsigned long port_type);
+extern unsigned long read_mmio_reg_tnc(unsigned long port_type,
+	unsigned long reg);
+extern void write_mmio_reg_tnc(unsigned long port_type, unsigned long reg,
+	unsigned long value);
+#endif
+
+
+/*
+ * These are temporary macros used only within this header.
+ * Individual config options use these macros to generate macros that look
+ * like this:
+ *
+ * If CONFIG_FOO is defined
+ *  OPT_FOO_SYMBOL(a)
+ *  OPT_FOO_VALUE(a, b)
+ *  OPT_FOO_VOID_CALL(fn)
+ *  OPT_FOO_CALL(fn)
+ */
+#define OPTIONAL_VOID_CALL(fn) fn
+#define OPTIONAL_CALL(fn)			\
+	{								\
+		int __ret;					\
+		__ret = fn;					\
+		if(__ret) {					\
+			EMGD_ERROR_EXIT("EXIT");	\
+			return __ret;			\
+		}							\
+	}
+
+#define OPTIONAL_CALL_RET(ret, fn)      (ret) = (fn)
+
+/*
+ * Debug call macro should be used to call debug printing functions
+ * that will only exist in debug builds.
+ */
+#ifdef DEBUG_BUILD_TYPE
+#define OPT_DEBUG_SYMBOL(sym)      sym
+#define OPT_DEBUG_VALUE(val, alt)  val
+#define OPT_DEBUG_VOID_CALL(fn)    OPTIONAL_VOID_CALL(fn)
+#define OPT_DEBUG_CALL(fn)         OPTIONAL_CALL(fn)
+#define OPT_DEBUG_INLINE
+#else
+#define OPT_DEBUG_SYMBOL(sym)
+#define OPT_DEBUG_VALUE(val, alt)  alt
+#define OPT_DEBUG_VOID_CALL(fn)
+#define OPT_DEBUG_CALL(fn)
+#define OPT_DEBUG_INLINE           static __inline
+#endif
+
+/*
+ * Micro Symbols are only used when CONFIG_MICRO is not defined.
+ */
+#ifndef CONFIG_MICRO
+#define OPT_MICRO_SYMBOL(sym)         sym
+#define OPT_MICRO_VALUE(val, alt)     val
+#define OPT_MICRO_VOID_CALL(fn)       OPTIONAL_VOID_CALL(fn)
+#define OPT_MICRO_CALL(fn)            OPTIONAL_CALL(fn)
+#define OPT_MICRO_CALL_RET(ret, fn)   OPTIONAL_CALL_RET(ret, fn)
+#else
+#define OPT_MICRO_SYMBOL(sym)
+#define OPT_MICRO_VALUE(val, alt)  alt
+#define OPT_MICRO_VOID_CALL(fn)
+#define OPT_MICRO_CALL(fn)
+#define OPT_MICRO_CALL_RET(ret, fn)
+#endif
+
+
+#ifdef CONFIG_PLB
+#define DISPATCH_PLB(p) {PCI_DEVICE_ID_VGA_PLB, p},
+#else
+#define DISPATCH_PLB(p)
+#endif
+#ifdef CONFIG_TNC
+#define DISPATCH_TNC(p) {PCI_DEVICE_ID_VGA_TNC, p},
+#define DISPATCH_TNC_A0(p) {PCI_DEVICE_ID_VGA_TNC_A0, p},
+#define DISPATCH_LNC(p) {PCI_DEVICE_ID_VGA_LNC, p},
+#else
+#define DISPATCH_TNC(p)
+#define DISPATCH_TNC_A0(p)
+#define DISPATCH_LNC(p)
+#endif
+#define DISPATCH_END {0, NULL}
+
+
+#endif // _UTILS_H_
+
diff --git a/drivers/gpu/drm/emgd/emgd/include/vga.h b/drivers/gpu/drm/emgd/emgd/include/vga.h
new file mode 100644
index 0000000..1c9b782
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/include/vga.h
@@ -0,0 +1,116 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: vga.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Header file for common VGA registers and macros.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _HAL_VGA_H
+#define _HAL_VGA_H
+
+#include <igd_vga.h>
+#include <io.h>
+#include "drm_emgd_private.h"
+
+extern void program_pipe_vga(
+	igd_display_context_t *display,
+	igd_timing_info_t *timings);
+
+extern void kms_program_pipe_vga(
+	emgd_crtc_t *emgd_crtc,
+	igd_timing_info_t *timings);
+
+extern void program_plane_vga(
+	igd_display_context_t *display,
+	igd_timing_info_t *timings);
+
+extern void kms_program_plane_vga(
+	unsigned char *mmio,
+	igd_timing_info_t *timings);
+
+extern unsigned long get_vga_color(int i);
+
+extern void set_256_palette(unsigned char *mmio);
+
+extern unsigned char vga_port_offset;
+
+#define READ_VGA(mmio, port, index, data) \
+  EMGD_WRITE8((unsigned char)index, EMGD_MMIO(mmio) + port); \
+  data = EMGD_READ8(EMGD_MMIO(mmio) + port + 1);
+
+#define WRITE_VGA(mmio, port, index, data) \
+  EMGD_WRITE8(index, EMGD_MMIO(mmio) + port); \
+  EMGD_WRITE8(data, EMGD_MMIO(mmio) + port + 1); \
+  EMGD_DEBUG("0x%lx (0x%lx): 0x%lx", (unsigned long) port, \
+		  (unsigned long) index, (unsigned long) data);
+
+#define READ_AR(mmio, index, data) \
+ { \
+	 unsigned char tmp; \
+	 tmp = EMGD_READ8(EMGD_MMIO(mmio) + ST01); \
+     EMGD_WRITE8(index, EMGD_MMIO(mmio) + AR_PORT); \
+     data = EMGD_READ8(EMGD_MMIO(mmio) + ARX_DATA_R); \
+	 tmp = EMGD_READ8(EMGD_MMIO(mmio) + ST01); \
+ }
+
+#define WRITE_AR(mmio, index, data) \
+ { \
+    unsigned char tmp; \
+	tmp = EMGD_READ8(EMGD_MMIO(mmio) + ST01); \
+	EMGD_WRITE8(index, EMGD_MMIO(mmio) + AR_PORT); \
+    EMGD_WRITE8(data, EMGD_MMIO(mmio) + AR_PORT); \
+	EMGD_WRITE8(0x20, EMGD_MMIO(mmio) + AR_PORT); \
+	tmp = EMGD_READ8(EMGD_MMIO(mmio) + ST01); \
+}
+
+/* Status registers */
+#define ST00 0x3C2
+#define ST01 (0x3BA + vga_port_offset)
+
+/* Sequencer Registers */
+#define SR_PORT   0x3c4
+#define SRX_INDEX 0x3C4   /* Index port */
+#define SRX_DATA  0x3C5   /* Data port */
+
+/* Graphics Registers */
+#define GR_PORT   0x3ce
+#define GRX_INDEX 0x3CE   /* Index port */
+#define GRX_DATA  0x3CF   /* Data port */
+
+/* Attribute Controlller Registers */
+#define AR_PORT    0x3c0
+#define ARX_INDEX  0x3C0   /* Index port */
+#define ARX_DATA_R 0x3C1   /* Data port read */
+#define ARX_DATA_W 0x3C0   /* Data port write */
+
+/* CRTC Registers */
+#define CR_PORT   (0x3b4 + vga_port_offset)
+#define CRX_INDEX (0x3b4 + vga_port_offset)  /* Index port */
+#define CRX_DATA (0x3b5 + vga_port_offset)  /* Data port */
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/oal/src/math_fix.c b/drivers/gpu/drm/emgd/emgd/oal/src/math_fix.c
new file mode 100644
index 0000000..84e5811
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/oal/src/math_fix.c
@@ -0,0 +1,138 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: math_fix.c
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains fixed point implementations of math functions
+ *-----------------------------------------------------------------------------
+ */
+
+
+/******************************************************************************
+ * This is a look-up table for natural log for integer values 1 - 255 in
+ * 24i.8f fixed point format.
+ *
+ * This table returns 0 or ln(0), but it is technically undefined.
+ *****************************************************************************/
+static const int ln_table[] =
+  {
+    0,    0,  177,  281,  355,  412,  459,  498,  532,  562,  589,  614,
+    636,  657,  676,  693,  710,  725,  740,  754,  767,  779,  791,  803,
+    814,  824,  834,  844,  853,  862,  871,  879,  887,  895,  903,  910,
+    917,  924,  931,  938,  944,  951,  957,  963,  969,  975,  980,  986,
+    991,  996, 1001, 1007, 1012, 1016, 1021, 1026, 1030, 1035, 1039, 1044,
+    1048, 1052, 1057, 1061, 1065, 1069, 1073, 1076, 1080, 1084, 1088, 1091,
+    1095, 1098, 1102, 1105, 1109, 1112, 1115, 1119, 1122, 1125, 1128, 1131,
+    1134, 1137, 1140, 1143, 1146, 1149, 1152, 1155, 1158, 1160, 1163, 1166,
+    1168, 1171, 1174, 1176, 1179, 1181, 1184, 1186, 1189, 1191, 1194, 1196,
+    1199, 1201, 1203, 1206, 1208, 1210, 1212, 1215, 1217, 1219, 1221, 1223,
+    1226, 1228, 1230, 1232, 1234, 1236, 1238, 1240, 1242, 1244, 1246, 1248,
+    1250, 1252, 1254, 1256, 1258, 1260, 1261, 1263, 1265, 1267, 1269, 1270,
+    1272, 1274, 1276, 1278, 1279, 1281, 1283, 1284, 1286, 1288, 1289, 1291,
+    1293, 1294, 1296, 1298, 1299, 1301, 1302, 1304, 1306, 1307, 1309, 1310,
+    1312, 1313, 1315, 1316, 1318, 1319, 1321, 1322, 1324, 1325, 1327, 1328,
+    1329, 1331, 1332, 1334, 1335, 1336, 1338, 1339, 1341, 1342, 1343, 1345,
+    1346, 1347, 1349, 1350, 1351, 1353, 1354, 1355, 1356, 1358, 1359, 1360,
+    1361, 1363, 1364, 1365, 1366, 1368, 1369, 1370, 1371, 1372, 1374, 1375,
+    1376, 1377, 1378, 1380, 1381, 1382, 1383, 1384, 1385, 1387, 1388, 1389,
+    1390, 1391, 1392, 1393, 1394, 1395, 1397, 1398, 1399, 1400, 1401, 1402,
+    1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1415,
+    1416, 1417, 1418, 1419
+  };
+
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: os_pow_fix()
+ *
+ * Parameters:
+ *    [IN] base:  the base, should be between 0 and 255.
+ *    [IN] power:  this must be in 24i.8f format.
+ *
+ * Description:
+ *    This function uses the Taylor Series to approximate the power function
+ *    using fixed-point math.  See this website for the math background
+ *    http://www.efunda.com/math/taylor_series/exponential.cfm
+ *
+ *    This function was originally designed for gamma correction.  When the
+ *    base value is between 1 - 255 and the power is between 0.1 and 2, this
+ *    function will produce an approximation that is within 2% of the "real"
+ *    function.
+ *
+ * Returns:
+ *    The result in 24i.8f format
+ *
+ *----------------------------------------------------------------------------
+ */
+
+unsigned int os_pow_fix( const int base, const int power )
+{
+  /* For some reason using "const unsigned int" causes a compiler error
+   * when I use it below when I declare "result[APPROXIMATE_TERMS]".  So
+   * switched these from "const unsigned .." to #define
+   */
+  #define APPROXIMATE_TERMS     40
+#define FRACTION_BITS         8    /* num of bits for fraction */
+
+  unsigned int       result[APPROXIMATE_TERMS];
+  unsigned int       i, power_loop;
+  unsigned int       total  = 0;
+  int                ln_x   = ln_table[base];  /* ln_x is in 24i.8f format */
+
+
+  /* nothing to do if we get 0 */
+  if (0 == base) {
+    return 0;
+  } else {
+    ln_x = ln_table[base];
+  }
+
+  /* We approximate the result using APPROXIMATE_TERMS terms */
+  for (i = 0; i < APPROXIMATE_TERMS; i++)    {
+
+    result[i] = 1 << FRACTION_BITS;
+
+    /* Need to be very careful about the order in which we are multiplying
+     * multiplying and dividing because we don't want any overflow.  In
+     * addition, every time we multiply 2 fixed point numbers, we need to
+     * shift the result by FRACTION_BITS to maintain the radix point.
+     */
+    for( power_loop = 0; power_loop < i; power_loop++ )    {
+      result[i] *= ln_x;
+      result[i] /= (power_loop + 1);
+      result[i] >>=FRACTION_BITS;
+      result[i] *= power;
+      result[i] >>=FRACTION_BITS;
+
+    }
+
+    total += result[i];
+
+  }
+
+  return total;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/oal/src/memmap.c b/drivers/gpu/drm/emgd/emgd/oal/src/memmap.c
new file mode 100644
index 0000000..2ee0812
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/oal/src/memmap.c
@@ -0,0 +1,55 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: memmap.c
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains the XFree86 implementations of the OAL
+ *  memory.h abstractions.
+ *-----------------------------------------------------------------------------
+ */
+#include <io.h>
+
+#ifndef _OAL_LINUX_KERNEL_IO_MEMMAP_H
+#define _OAL_LINUX_KERNEL_IO_MEMMAP_H
+
+
+void * os_map_io_to_mem_nocache(
+				unsigned long base_address,
+				unsigned long size
+				)
+{
+  return ioremap(base_address, size);
+}
+
+void os_unmap_io_from_mem(
+			  void * virt_addr,
+			  unsigned long size
+			  )
+{
+  iounmap(virt_addr);
+}
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/oal/src/pci.c b/drivers/gpu/drm/emgd/emgd/oal/src/pci.c
new file mode 100644
index 0000000..ff8a28c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/oal/src/pci.c
@@ -0,0 +1,277 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pci.c
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains Linux kernel space PCI API for the OAL abstractions.
+ *-----------------------------------------------------------------------------
+ */
+
+#include <memory.h>
+#include <pci.h>
+#include <linux/pci.h>
+#include <io.h>
+
+#if defined(CONFIG_VGA_ARB)
+#include <linux/vgaarb.h>
+#endif
+
+
+//
+// This is our local representation of a PCI device.
+// This struct is private to this file, and exposed to calling functions
+// only through an opaque "os_pci_dev_t" handle.
+//
+typedef struct _linuxkernel_pci {
+  struct pci_dev *dev;
+  unsigned int bus;
+  unsigned int slot;
+  unsigned int func;
+}linuxkernel_pci_t;
+
+/*----------------------------------------------------------------------
+ * Function:
+ *pci_find_device_generic
+ * Parameters:
+ *unsigned short vendor,
+ *unsigned short device,
+ *os_pci_dev_t os_pci_dev
+ * Description:
+ *This function finds a PCI device by going through 255 buses, 32 devices
+ *and 8 functions and tries to match each ones vendor and device ids with
+ *the ones given to it as parameters. Stops for the first device it finds
+ *with a matching vendor and device, so it will not find multiple devices.
+ *This is _NOT_ an exported OAL
+ *function.
+ * Returns:
+ *os_pci_dev_t
+ *---------------------------------------------------------------------
+ */
+static os_pci_dev_t pci_find_device_generic(
+					    unsigned short vendor_id,
+					    unsigned short device_id,
+					    os_pci_dev_t pci_dev_handle
+					    )
+{
+  struct pci_dev *our_device; // Kernel struct for a PCI device
+  linuxkernel_pci_t *pdev; // Our struct for a PCI device.
+
+    // Locate the device, and lock it. Start search at the start of the list.
+    our_device = pci_get_device(vendor_id, device_id, NULL);
+    // If we didn't find it, return an error.
+    if (!our_device){
+      return (os_pci_dev_t)NULL;
+    }
+
+    // Get the pointer to the destination for the data.
+    // pci_dev_handle is an opaque pointer to a linuxkernel_pci_t struct
+    // If there isn't one, allocate it.
+    pdev = (linuxkernel_pci_t *)pci_dev_handle;
+    if(!pdev) {
+
+      // Caller did not supply a handle to a PCI device struct.
+      // Allocate one.
+      pdev = (linuxkernel_pci_t *)OS_ALLOC(sizeof(linuxkernel_pci_t));
+      if(!pdev) {
+	return (os_pci_dev_t)NULL;
+      }
+      // Zero the destination memory
+      memset(pdev, 0, sizeof(linuxkernel_pci_t));
+    }
+
+    // Copy over from the kernel struct to our struct.
+    // It is safe to copy a pointer to the pci_dev, since we
+    // have a lock on it.
+    pdev->dev = our_device;
+    pdev->bus = our_device->bus->number;
+    pdev->slot = PCI_SLOT(our_device->devfn);
+    pdev->func = PCI_FUNC(our_device->devfn);
+
+    return (os_pci_dev_t)pdev;
+}
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ *os_pci_find_device
+ *
+ *  Parameters:
+ *unsigned short vendor,
+ *unsigned short device,
+ *unsigned short bus,
+ *unsigned short dev,
+ *unsigned short func,
+ *os_pci_dev_t os_pci_dev
+ *
+ *  Description:
+ *  This function finds a PCI device by scanning the specified bus, dev, func
+ *and tries to match vendor and device ids with the ones given to it as
+ *parameters.
+ *
+ *  Notes: If the bus number is 0xFFFF, then the function searches for that
+ *  vendor_id, device_id pair in the whole PCI topology of the system i.e
+ *  it goes through all the buses, devices, functions in the system
+ *
+ * Returns:
+ *os_pci_dev_t
+ *---------------------------------------------------------------------
+ */
+os_pci_dev_t os_pci_find_device(
+				unsigned short vendor_id,
+				unsigned short device_id,
+				unsigned short bus,
+				unsigned short dev,
+				unsigned short func,
+				os_pci_dev_t pci_dev)
+{
+  /* TODO: Right now, Just fallback to pci_find_device_generic
+   * But we need to implement this
+   */
+  return pci_find_device_generic(vendor_id, device_id, pci_dev);
+}
+
+int os_pci_get_slot_address(
+			    os_pci_dev_t pci_dev,
+			    unsigned int *bus,
+			    unsigned int *slot,
+			    unsigned int *func)
+{
+
+  linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+  EMGD_ASSERT(pdev, "Invalid pci device", 0);
+
+  if(bus) {
+    *bus = pdev->bus;
+  }
+  if(slot) {
+    *slot = pdev->slot;
+  }
+  if(func) {
+    *func = pdev->func;
+  }
+  return 0;
+}
+
+int os_pci_read_config_8(
+			 os_pci_dev_t pci_dev,
+			 unsigned long offset,
+			 unsigned char* val
+			 )
+{
+  linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+  EMGD_ASSERT(pdev, "Invalid pci device", 0);
+  EMGD_ASSERT(val, "Invalid pointer", 0);
+  return pci_read_config_byte(pdev->dev, offset, val);
+}
+
+int os_pci_read_config_16(
+			  os_pci_dev_t pci_dev,
+			  unsigned long offset,
+			  unsigned short* val
+			  )
+{
+  linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+  EMGD_ASSERT(pdev, "Invalid pci device", 0);
+  EMGD_ASSERT(val, "Invalid pointer", 0);
+  return pci_read_config_word(pdev->dev, offset,val);
+}
+
+int os_pci_read_config_32(
+			  os_pci_dev_t pci_dev,
+			  unsigned long offset,
+			  unsigned long* val
+			  )
+{
+  linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+  EMGD_ASSERT(pdev, "Invalid pci device", 0);
+  EMGD_ASSERT(val, "Invalid pointer", 0);
+  return pci_read_config_dword(pdev->dev, offset, (u32*)val);
+}
+
+int os_pci_write_config_8(
+			  os_pci_dev_t pci_dev,
+			  unsigned long offset,
+			  unsigned char val
+			  )
+{
+  linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+  EMGD_ASSERT(pdev, "Invalid pci device", 0);
+  return pci_write_config_byte(pdev->dev, offset, val);
+}
+
+int os_pci_write_config_16(
+			   os_pci_dev_t pci_dev,
+			   unsigned long offset,
+			   unsigned short val
+			   )
+{
+  linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+  EMGD_ASSERT(pdev, "Invalid pci device", 0);
+  return pci_write_config_word(pdev->dev, offset, val);
+}
+
+int os_pci_write_config_32(
+			   os_pci_dev_t pci_dev,
+			   unsigned long offset,
+			   unsigned long val
+			   )
+{
+  linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+  EMGD_ASSERT(pdev, "Invalid pci device", 0);
+  return pci_write_config_dword(pdev->dev, offset, val);
+}
+
+int os_pci_disable_legacy_vga_decoding(
+			os_pci_dev_t pci_dev
+		)
+{
+#if defined(CONFIG_VGA_ARB)
+	linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+	EMGD_ASSERT(pdev, "Invalid pci device", 0);
+
+	vga_set_legacy_decoding(pdev->dev, VGA_RSRC_NONE);
+#else
+	/* Noop if the VGA arbiter isn't compiled into the kernel */
+#endif
+
+	return 0;
+}
+
+
+void os_pci_free_device(
+			os_pci_dev_t pci_dev
+			)
+{
+  linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+
+  // Release the lock on our PCI device struct
+  pci_dev_put(pdev->dev);
+
+  // Free our local structure.
+  OS_FREE(pdev);
+
+  return;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/Makefile.include b/drivers/gpu/drm/emgd/emgd/pal/Makefile.include
new file mode 100644
index 0000000..c312c51
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/Makefile.include
@@ -0,0 +1,50 @@
+#----------------------------------------------------------------------------
+# Filename: Makefile.include
+# $Revision: 1.3 $
+#----------------------------------------------------------------------------
+# Copyright (c) 2002-2010, Intel Corporation.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#----------------------------------------------------------------------------
+
+ifeq ($(origin EGD_CFG), undefined)
+$(error EGD_CFG environment variable is required for compilation)
+endif
+
+EGD_ROOT := $(subst  \,/,$(EGD_ROOT))
+
+#
+# PAL overrides the include paths because the HAL get access to more
+# headers that the port drivers cannot use.
+#
+PROJECT_INCLUDES := \
+	$(EGD_ROOT)/hal/include \
+	$(EGD_ROOT)/$(EGD_CFG)/include \
+	$(EGD_ROOT)/$(EGD_CFG)/oal/include \
+	$(EGD_ROOT)/$(EGD_CFG)/oal \
+	$(EGD_ROOT)/$(EGD_CFG)/pal/lpd
+
+PROJECT_LIBS=\
+	$(EGD_ROOT)/$(EGD_CFG)/cfg/lib/liblpd
+
+PROJECT_BUILD_OPTS = -DMODULE_NAME=hal.dpd
+
+PROJECT_OUTPUT_PATH = $(EGD_ROOT)/$(EGD_CFG)/cfg/dpd
+
+include $(EGD_ROOT)/$(EGD_CFG)/build/Makefile.include
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/Makefile.gnu b/drivers/gpu/drm/emgd/emgd/pal/ch7036/Makefile.gnu
new file mode 100644
index 0000000..cb82fd6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/Makefile.gnu
@@ -0,0 +1,44 @@
+#----------------------------------------------------------------------------
+# 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/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.c
new file mode 100755
index 0000000..3b588a9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.c
@@ -0,0 +1,2366 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file  ch7036.c
+* @version 1.2.2.1
+*-----------------------------------------------------------------------------
+*/
+
+
+
+#include "ch7036_intf.h"
+
+
+static uint32 g_nLastError;
+
+
+
+static ch_bool convert_pll1n1_div(ch_bool pll1n1_to_div, uint8* pll1n1_addr, uint8* div_addr); 
+static ch_bool convert_pll1n2_div(ch_bool pll1n2_to_div, uint8* pll1n2_addr, uint8* div_addr);
+static ch_bool convert_pll1n3_div(ch_bool pll1n3_to_div, uint8* pll1n3_addr, uint8* div_addr);
+static ch_bool convert_pll2n5_div(ch_bool pll2n5_to_div, uint8* pll2n5_addr, uint8* div_addr);
+static ch_bool convert_pll2n6_div(ch_bool pll2n6_to_div, uint8* pll2n6_addr, uint8* div_addr);
+static ch_bool convert_pll2n7_div(ch_bool pll2n7_to_div, uint8* pll2n7_addr, uint8* div_addr);
+static ch_bool convert_pll3n8_div(ch_bool pll3n8_to_div, uint8* pll3n8_addr, uint8* div_addr);
+static ch_bool convert_dmxtal_div(ch_bool dmxtal_to_div, uint8* dmxtal_addr, uint8* div_addr);
+
+
+static ch_bool set_input_info(INPUT_INFO* pInput_Info);
+
+
+static ch_bool set_output_info(OUTPUT_INFO* pOutput_Info);
+
+
+static ch_bool set_prefer_info(PREFER_INFO* pPrefer_Info);
+
+
+static ch_bool cal_and_set_clk_pll(DEV_CONTEXT* pDevContext);
+
+
+static ch_bool cal_and_set_scaler(DEV_CONTEXT* pDevContext);
+
+
+static ch_bool cal_and_set_power(DEV_CONTEXT* pDevContext);
+
+
+static ch_bool post_cal_and_set(DEV_CONTEXT* pDevContext);
+
+
+extern void ch7036_set_power_lvds(DEV_CONTEXT* pDevContext);
+extern void ch7036_set_power_hdmi(DEV_CONTEXT* pDevContext);
+extern void ch7036_set_power_crt(DEV_CONTEXT* pDevContext);
+
+
+#define  DOUBLE_TO_INT		1000
+
+
+
+
+
+
+
+ch_bool DeviceSetPower(DEV_CONTEXT* pDevContext, unsigned long flags)
+{
+
+	switch (flags) {
+		default:
+			ch7036_set_power_crt(pDevContext);
+			ch7036_set_power_hdmi(pDevContext);
+			ch7036_set_power_lvds(pDevContext);
+			break;
+	}
+
+	return ch_true;
+
+}
+
+ch_bool DevicePrepare(DEV_CONTEXT* pDevContext)
+{
+	uint32 C;
+	uint32 hao_t, vao_t, vai_t, val_t;
+	uint32 hai_down;
+	uint32 hai_sdram;
+	uint32 lnsel;
+	uint32 intlc = 0;
+	uint32 blk_h;
+	uint32 fba_inc;
+	uint32 bandwidth;
+
+	uint32 frame_rate_in, frame_rate_out;  
+	uint32  r;                             
+
+	INPUT_INFO* pInput_Info = pDevContext->pInput_Info;
+	OUTPUT_INFO* pOutput_Info = pDevContext->pOutput_Info;
+	PREFER_INFO* pPrefer_Info = pDevContext->pPrefer_Info;
+
+	
+	g_nLastError = ERR_NO_ERROR;
+
+	
+	I2CWrite(pDevContext,0x03, 0x04);
+	pDevContext->DeviceID = I2CRead(pDevContext,0x50);
+	if(pDevContext->DeviceID != 0x56)
+	{
+		g_nLastError = ERR_DEVICE_NO_EXIST;
+		return ch_false;
+	}
+
+	
+	
+	if(pInput_Info->timing.ha % 2)
+	{
+		pInput_Info->timing.ha--;	
+	}
+	if(pInput_Info->timing.va % 2)
+	{
+		pInput_Info->timing.va--;	
+	}
+
+	
+	
+	if(pPrefer_Info->dat16_32b)
+	{
+		C = 100;
+	}
+	else if(pPrefer_Info->true24)
+	{
+		C = 100;
+	}
+	else
+	{
+		C = (pPrefer_Info->true_com) ? 75 : 50;
+	}
+	if(pOutput_Info->ds_percent_h)
+	{
+		hao_t = pOutput_Info->timing.ha * (100 - pOutput_Info->ds_percent_h) / 100;
+	}
+	else
+	{
+		hao_t = pOutput_Info->timing.ha;
+	}
+	if(pOutput_Info->ds_percent_v)
+	{
+		vao_t = pOutput_Info->timing.va * (100 - pOutput_Info->ds_percent_v) / 100;
+	}
+	else
+	{
+		vao_t = pOutput_Info->timing.va;
+	}
+	hao_t = hao_t + (hao_t % 2);
+	vao_t = vao_t + (vao_t % 2);
+	hai_down = pInput_Info->timing.ha;
+	if(hai_down > hao_t && pOutput_Info->rotate != ROTATE_90 && pOutput_Info->rotate != ROTATE_270)
+	{
+		hai_down = hao_t;
+	}
+
+	if(pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270)
+	{
+		val_t = 720;
+	}
+	else
+	{
+		if(pPrefer_Info->dat16_32b)
+		{
+			val_t = 720;
+		}
+		else
+		{
+			val_t = pPrefer_Info->true24 ? 720 : 1440;
+		}
+	}
+	if(hai_down > val_t && (pOutput_Info->rotate != ROTATE_NO || pOutput_Info->h_flip || pOutput_Info->v_flip))
+	{
+		hai_down = val_t;
+	}
+
+	if(pOutput_Info->channel & CHANNEL_HDMI)
+	{
+		
+		switch(pOutput_Info->hdmi_fmt.format_index)
+		{
+		case  5:
+		case  6:
+		case  7:
+		case 10:
+		case 11:
+		case 20:
+		case 21:
+		case 22:
+		case 25:
+		case 26:
+			intlc = 1;
+			break;
+		default:
+			intlc = 0;
+			break;		
+		}
+	}
+
+	
+	if(pOutput_Info->channel & CHANNEL_VGA)
+	{
+       intlc = 0;
+	}
+
+	val_t = intlc ? (vao_t / 2) : vao_t;
+	if(pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270)
+	{
+		if(hai_down <= val_t)
+			lnsel = 3;
+		else
+			lnsel = 1;
+	}
+	else
+	{
+		if(pInput_Info->timing.va <= val_t)
+			lnsel = 3;
+		else
+			lnsel = 1;
+	}
+	bandwidth = (pInput_Info->rx_clk_khz + pOutput_Info->uclk_khz * pInput_Info->timing.ha / hao_t * (4 - lnsel)) / 85 * C;
+	if(bandwidth > MEM_CLK_FREQ_MAX)
+	{
+		if(lnsel >= 2)
+		{
+			g_nLastError = ERR_BANDWIDTH_OVERFLOW;
+			return ch_false;
+		}
+		
+		lnsel++;
+
+		
+		
+		
+		
+		
+		if(pInput_Info->rx_clk_khz >= 75428 && pOutput_Info->uclk_khz >= 94500)
+			lnsel++;
+
+		bandwidth = (pInput_Info->rx_clk_khz + pOutput_Info->uclk_khz * pInput_Info->timing.ha / hao_t * (4 - lnsel)) / 85 * C;
+		if(bandwidth > MEM_CLK_FREQ_MAX)
+		{
+			g_nLastError = ERR_BANDWIDTH_OVERFLOW;
+			return ch_false;
+		}
+		pPrefer_Info->scale_line_adjust = 1;
+	}
+
+	
+	if(pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270)
+	{
+		val_t = 100;
+	}
+	else
+	{
+		if(pPrefer_Info->dat16_32b)
+		{
+			val_t = 100;
+		}
+		else if(pPrefer_Info->true24)
+		{
+			val_t = 100;
+		}
+		else
+		{
+			val_t = pPrefer_Info->true_com ? 75 : 50;
+		}
+	}
+	if(val_t == 75)
+	{
+		hai_sdram = (hai_down / 4) * 3 + (hai_down % 4);
+	}
+	else
+	{
+		hai_sdram = hai_down * val_t / 100;
+	}
+	if(pOutput_Info->rotate != ROTATE_NO || pOutput_Info->h_flip || pOutput_Info->v_flip)
+	{
+		blk_h = 45;
+	}
+	else if(hai_sdram <= 720 && pInput_Info->timing.va <= 720)
+	{
+		blk_h = 45;
+	}
+	else
+	{
+		blk_h = hai_sdram / 16;
+		blk_h = (hai_sdram % 16) ? (blk_h + 1) : blk_h;
+	}
+
+	
+	if((pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270) && pPrefer_Info->true24 == 0 && pPrefer_Info->true_com == 0 && pPrefer_Info->dat16_32b == 0)
+	{
+		vai_t = pInput_Info->timing.va / 2;
+	}
+	else
+	{
+		vai_t = pInput_Info->timing.va;
+	}
+	val_t = (vai_t % 16) ? (vai_t / 16 + 1) : (vai_t / 16);
+	fba_inc = blk_h * val_t;
+
+	
+	frame_rate_in = ((pInput_Info->rx_clk_khz * 10000) / pInput_Info->timing.ht) * 10 / pInput_Info->timing.vt;
+	frame_rate_out = ((pOutput_Info->uclk_khz * 10000) / pOutput_Info->timing.ht) * 10 / pOutput_Info->timing.vt;
+	r = DOUBLE_TO_INT*frame_rate_in / frame_rate_out;
+
+	
+	if(pPrefer_Info->dat16_32b)
+	{
+		if(pPrefer_Info->true24)
+		{
+			g_nLastError = ERR_NO_SUPPORT_TRUE24;
+			return ch_false;
+		}
+		if(pPrefer_Info->true_com)
+		{
+			g_nLastError = ERR_NO_SUPPORT_TRUECOM;
+			return ch_false;
+		}
+		if(pOutput_Info->rotate == ROTATE_NO && pOutput_Info->h_flip == 0 && pOutput_Info->v_flip == 0)
+		{
+			if(fba_inc > FBA_INC_MAX)
+			{
+				
+				
+				
+               if (( (DOUBLE_TO_INT/2) <= r) && ( r <= DOUBLE_TO_INT))
+			   {
+					if( ((4096*DOUBLE_TO_INT) / fba_inc) < (2*DOUBLE_TO_INT-r) )
+					{
+						g_nLastError = ERR_RESOLUTION_OVERFLOW;
+						return ch_false;
+					}
+			   }
+  
+               if (( DOUBLE_TO_INT < r) && ( r <= (2*DOUBLE_TO_INT)))
+			   {
+					if( ((4096*DOUBLE_TO_INT) / fba_inc)  <
+						(2*DOUBLE_TO_INT - (DOUBLE_TO_INT*DOUBLE_TO_INT)/r) )
+					{
+						g_nLastError = ERR_RESOLUTION_OVERFLOW;
+						return ch_false;
+					}
+			   }		
+			   
+			}
+		}
+		else if(pOutput_Info->rotate != ROTATE_NO)	
+		{
+			if(pInput_Info->timing.va > 720)
+			{
+				g_nLastError = ERR_ROTATION_WITH_VAI;
+				return ch_false;
+			}
+		}
+		else 
+		{
+			if(pInput_Info->timing.va > 720)
+			{
+				g_nLastError = ERR_FLIP_WITH_VAI;
+				return ch_false;
+			}
+		}
+	}
+
+	
+	if(pPrefer_Info->dat16_32b == 0)
+	{
+		if(pOutput_Info->rotate == ROTATE_NO && pOutput_Info->h_flip == 0 && pOutput_Info->v_flip == 0)
+		{	
+			if(fba_inc > FBA_INC_MAX)	
+			{
+				
+                if (( (DOUBLE_TO_INT/2) <= r) && ( r <= DOUBLE_TO_INT))
+			    {
+					if( ((4096*DOUBLE_TO_INT) / fba_inc) < (2*DOUBLE_TO_INT-r) )
+					{
+						g_nLastError = ERR_RESOLUTION_OVERFLOW;
+						return ch_false;
+					}
+			    }
+  
+                if (( DOUBLE_TO_INT < r) && ( r <= (2*DOUBLE_TO_INT)))
+			    {
+					if( ((4096*DOUBLE_TO_INT) / fba_inc)  <
+						(2*DOUBLE_TO_INT - (DOUBLE_TO_INT*DOUBLE_TO_INT)/r) )
+					{
+						g_nLastError = ERR_RESOLUTION_OVERFLOW;
+						return ch_false;
+					}
+			    }		
+			    
+
+				if(pPrefer_Info->true24)
+				{
+					g_nLastError = ERR_NO_SUPPORT_TRUE24;
+					return ch_false;
+				}
+				if(pPrefer_Info->true_com)
+				{
+					g_nLastError = ERR_NO_SUPPORT_TRUECOM;
+					return ch_false;
+				}
+				g_nLastError = ERR_RESOLUTION_OVERFLOW;
+				return ch_false;
+			}
+		}
+		if(pOutput_Info->rotate == ROTATE_180)
+		{
+			if(pPrefer_Info->true_com)
+			{
+				g_nLastError = ERR_NO_SUPPORT_TRUECOM;
+				return ch_false;
+			}
+			if(pPrefer_Info->true24)
+			{
+				if(pInput_Info->timing.va > 720)
+				{
+					g_nLastError = ERR_NO_SUPPORT_TRUE24;
+					return ch_false;
+				}
+			}
+			else
+			{
+				if(pInput_Info->timing.va > 720)
+				{
+					g_nLastError = ERR_ROTATION_WITH_VAI;
+					return ch_false;
+				}
+			}
+		}
+		if(pOutput_Info->h_flip || pOutput_Info->v_flip)
+		{
+			if(pPrefer_Info->true_com)
+			{
+				g_nLastError = ERR_NO_SUPPORT_TRUECOM;
+				return ch_false;
+			}
+			if(pInput_Info->timing.va > 720)
+			{
+				g_nLastError = ERR_FLIP_WITH_VAI;
+				return ch_false;
+			}
+		}
+		if(pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270)
+		{
+			if(pPrefer_Info->true_com)
+			{
+				g_nLastError = ERR_NO_SUPPORT_TRUECOM;
+				return ch_false;
+			}
+			if(pPrefer_Info->true24)
+			{
+				if(pInput_Info->timing.va > 720)
+				{
+					g_nLastError = ERR_NO_SUPPORT_TRUE24;
+					return ch_false;
+				}
+			}
+			else
+			{
+				if(pInput_Info->timing.va > 1440)
+				{
+					g_nLastError = ERR_ROTATION_WITH_VAI;
+					return ch_false;
+				}
+			}
+		}
+	}
+
+	
+	
+	if(pPrefer_Info->true24 || pPrefer_Info->true_com)
+	{
+		pPrefer_Info->dither_filter_enable = 0;
+	}
+
+	
+
+	
+	iic_reset();
+
+	
+	if(pOutput_Info->channel & CHANNEL_HDMI || pOutput_Info->channel & CHANNEL_VGA) 
+	{
+	
+		iic_write(0x03, 0x01);  
+		iic_write(0x07, 0x7E);
+		iic_write(0x09, 0x0B);
+		iic_write(0x03, 0x00);
+		iic_write_ex(STOP, 1);
+	}
+
+	return ch_true;
+}
+
+ch_bool DeviceConfig(DEV_CONTEXT* pDevContext)
+{
+	if(!set_input_info(pDevContext->pInput_Info))
+		return ch_false;
+
+	if(!set_output_info(pDevContext->pOutput_Info))
+		return ch_false;
+
+	if(!set_prefer_info(pDevContext->pPrefer_Info))
+		return ch_false;
+
+	if(!cal_and_set_clk_pll(pDevContext))
+		return ch_false;
+
+	if(!cal_and_set_scaler(pDevContext))
+		return ch_false;
+
+	if(!cal_and_set_power(pDevContext))
+		return ch_false;
+
+	return ch_true;
+}
+
+ch_bool DeviceRunning(DEV_CONTEXT* pDevContext)
+{
+	uint8 val_t;
+	uint8 reg = 0x00;
+	OUTPUT_INFO* pOutput_Info = pDevContext->pOutput_Info;
+	PREFER_INFO* pPrefer_Info = pDevContext->pPrefer_Info;
+
+	uint8 REFDLY = pPrefer_Info->pll_ref_dly;
+	uint8 FBDLY = pPrefer_Info->pll_ref_fbdly;
+	uint8 TXDRV_IT = pPrefer_Info->lvds_txdrv_ctrl;
+
+	
+	DeviceReset(pDevContext);
+
+	
+	
+	DeviceSetup(pDevContext);
+	
+	
+	I2CWrite(pDevContext,0x03, 0x01);
+	
+	
+	
+	
+	reg = I2CRead(pDevContext,0x24) & 0xFD; 
+	I2CWrite(pDevContext,0x24, reg);
+
+	I2CWrite(pDevContext,0x03, 0x04);
+	reg = I2CRead(pDevContext,0x66);
+    reg = reg & 0x1F;
+	reg = reg | ((uint8)REFDLY << 5);
+	I2CWrite(pDevContext,0x66, reg); 
+
+	I2CWrite(pDevContext,0x03, 0x04);
+	reg = I2CRead(pDevContext,0x66);
+    reg = reg & 0xE3;
+	reg = reg | ((uint8)FBDLY << 2);
+	I2CWrite(pDevContext,0x66, reg);
+
+    I2CWrite(pDevContext,0x03, 0x04);
+	reg = I2CRead(pDevContext,0x68) & 0xF0;
+    reg = reg | ((uint8)TXDRV_IT);
+	I2CWrite(pDevContext,0x68, reg); 
+
+	
+
+
+
+	
+        
+       I2CWrite(pDevContext,0x03, 0x01);  
+	   reg = I2CRead(pDevContext,0x0D);
+	   if((pPrefer_Info->eye_dri_pll_rlf >= 0) && (pPrefer_Info->eye_dri_pll_rlf <= 3))
+ 	      reg = (reg & 0x9F) | (pPrefer_Info->eye_dri_pll_rlf << 5);
+	   I2CWrite(pDevContext,0x0D, reg);
+
+	   I2CWrite(pDevContext,0x03, 0x01);  
+	   reg = I2CRead(pDevContext,0x0C);
+	   if((pPrefer_Info->eye_dri_pll_cp >= 0) && (pPrefer_Info->eye_dri_pll_cp <= 3))
+ 	      reg = (reg & 0x3F) | (pPrefer_Info->eye_dri_pll_cp << 6);
+	   I2CWrite(pDevContext,0x0C, reg);
+
+	   I2CWrite(pDevContext,0x03, 0x01);  
+	   reg = I2CRead(pDevContext,0x0B);
+	   if((pPrefer_Info->eye_dri_damp >= 0) && (pPrefer_Info->eye_dri_damp <= 7))
+ 	      reg = (reg & 0x1F) | (pPrefer_Info->eye_dri_damp << 5);
+	   I2CWrite(pDevContext,0x0B, reg);
+
+       I2CWrite(pDevContext,0x03, 0x01);  
+	   reg = I2CRead(pDevContext,0x0A);
+	   if((reg & 0x01)==0x00)
+ 	      reg = (reg | 0x01);
+	   I2CWrite(pDevContext,0x0A, reg);
+
+       I2CWrite(pDevContext,0x03, 0x01);  
+	   reg = I2CRead(pDevContext,0x0A);
+	   if((pPrefer_Info->eye_dri_demp >= 0) && (pPrefer_Info->eye_dri_demp <= 15))
+ 	      reg = (reg & 0xE1) | (pPrefer_Info->eye_dri_demp << 1);
+	   I2CWrite(pDevContext,0x0A, reg);
+
+	   I2CWrite(pDevContext,0x03, 0x01);  
+	   reg = I2CRead(pDevContext,0x08);
+	   if((pPrefer_Info->eye_dacg >= 0) && (pPrefer_Info->eye_dacg <= 3))
+ 	      reg = (reg & 0x3F) | (pPrefer_Info->eye_dacg << 6);
+	   I2CWrite(pDevContext,0x08, reg);
+
+	   I2CWrite(pDevContext,0x03, 0x01);  
+	   reg = I2CRead(pDevContext,0x0F);
+	   if((pPrefer_Info->eye_rdac >= 0) && (pPrefer_Info->eye_rdac <= 7))
+ 	      reg = (reg & 0xC7) | (pPrefer_Info->eye_rdac << 3);
+	   I2CWrite(pDevContext,0x0F, reg);
+
+	   I2CWrite(pDevContext,0x03, 0x04);  
+	   reg = I2CRead(pDevContext,0x54);
+	   if((pPrefer_Info->eye_bgtrim >= 0) && (pPrefer_Info->eye_bgtrim <= 3))
+ 	      reg = (reg & 0xF3) | (pPrefer_Info->eye_bgtrim << 2);
+	   I2CWrite(pDevContext,0x54, reg);
+
+
+	
+
+	
+	if(pOutput_Info->channel & CHANNEL_HDMI || pOutput_Info->channel & CHANNEL_VGA) 
+	{
+		
+		if(!post_cal_and_set(pDevContext)){
+		   return ch_false;
+	    }
+
+		
+		I2CWrite(pDevContext,0x03, 0x00);
+		val_t = I2CRead(pDevContext,0x0A);
+		I2CWrite(pDevContext,0x0A, val_t | 0x80); 
+		I2CWrite(pDevContext,0x0A, val_t & 0x7F); 
+
+		
+
+
+		
+		
+		
+		
+		
+		
+	    
+	    
+		
+		
+		I2CWrite(pDevContext,0x03, 0x00);
+		val_t = I2CRead(pDevContext,0x0A);
+		I2CWrite(pDevContext,0x0A, val_t & 0xEF); 
+		
+		
+
+	}
+
+	return ch_true;
+}
+
+uint32 GetLastErrorMessage()
+{
+	return g_nLastError;
+}
+
+
+
+ch_bool set_input_info(INPUT_INFO* pInput_Info)
+{
+	
+	iic_write_ex(HTI, pInput_Info->timing.ht);
+	iic_write_ex(HAI, pInput_Info->timing.ha);
+	iic_write_ex(HOI, pInput_Info->timing.ho);
+	iic_write_ex(HWI, pInput_Info->timing.hw);
+	iic_write_ex(VTI, pInput_Info->timing.vt);
+	iic_write_ex(VAI, pInput_Info->timing.va);
+	iic_write_ex(VOI, pInput_Info->timing.vo);
+	iic_write_ex(VWI, pInput_Info->timing.vw);
+	
+	iic_write_ex(RCLK, pInput_Info->rx_clk_khz);
+	
+	
+	switch(pInput_Info->pixel_fmt)
+	{
+		  case 0:
+			 iic_write_ex(DITHER_SEL0_SPP, 0);
+		     iic_write_ex(DITHER_SEL1_SPP, 0);
+			 break;
+		  case 1:
+			 iic_write_ex(DITHER_SEL0_SPP, 1);
+		     iic_write_ex(DITHER_SEL1_SPP, 0);
+			 break;
+		  case 2:
+			 iic_write_ex(DITHER_SEL0_SPP, 0);
+		     iic_write_ex(DITHER_SEL1_SPP, 1);
+			 break;
+		  case 3:
+			 iic_write_ex(DITHER_SEL0_SPP, 1);
+		     iic_write_ex(DITHER_SEL1_SPP, 1);
+			 break;
+		  default:
+			iic_write_ex(DITHER_SEL0_SPP, 0);
+		    iic_write_ex(DITHER_SEL1_SPP, 0);
+			break;
+	}
+
+	
+	
+	iic_write_ex(HSYNCP_SPP, pInput_Info->hs_pol);
+	iic_write_ex(VSYNCP_SPP, pInput_Info->vs_pol);
+	
+	iic_write_ex(HPO_I, pInput_Info->hs_pol);
+	iic_write_ex(VPO_I, pInput_Info->vs_pol);
+	iic_write_ex(DEPO_I, pInput_Info->de_pol);
+	
+	iic_write_ex(NP_INV0_SPP, (pInput_Info->data_ch_pol & (1 << 0)) ? 1 : 0);
+	iic_write_ex(NP_INV1_SPP, (pInput_Info->data_ch_pol & (1 << 1)) ? 1 : 0);
+	iic_write_ex(NP_INV2_SPP, (pInput_Info->data_ch_pol & (1 << 2)) ? 1 : 0);
+	iic_write_ex(NP_INV3_SPP, (pInput_Info->data_ch_pol & (1 << 3)) ? 1 : 0);
+	
+	iic_write_ex(LVDS_IN_ORDER, pInput_Info->data_ch_invert);
+	
+	iic_write_ex(I2S_SPDIFB, pInput_Info->audio_type);
+	if(pInput_Info->audio_type == AUDIO_I2S) {
+		iic_write_ex(I2SPOL, pInput_Info->i2s_pol);
+		iic_write_ex(I2S_LENGTH, pInput_Info->i2s_len);
+		iic_write_ex(I2SFMT, pInput_Info->i2s_fmt);
+	}
+
+	return ch_true;
+}
+
+ch_bool set_output_info(OUTPUT_INFO* pOutput_Info)
+{
+	uint8 lvds0_seq, lvds1_seq, lvds2_seq, lvds3_seq, lvdsclk_seq;
+	uint8 lvds0_pol, lvds1_pol, lvds2_pol, lvds3_pol, lvdsclk_pol;
+	uint8 hd_dvib, intlc = 0, copy, hd_lv_pol, hd_lv_seq, hdmi_lvds_sel, hsp, vsp, m1m0, c1c0, vic; 
+	uint32 hao_down, vao_down;
+
+	
+	LVDS_FMT* pLvdsFmt = &pOutput_Info->lvds_fmt;
+	HDMI_FMT* pHdmiFmt = &pOutput_Info->hdmi_fmt;
+	
+	
+	
+
+
+	
+		
+
+
+
+	if(pOutput_Info->channel & CHANNEL_VGA || pOutput_Info->channel & CHANNEL_HDMI) {
+		iic_write_ex(VP,pOutput_Info->v_position);
+		iic_write_ex(HP,pOutput_Info->h_position);
+	}
+	
+
+	
+	if(pOutput_Info->channel & CHANNEL_HDMI || pOutput_Info->channel & CHANNEL_VGA)
+	{
+		iic_write_ex(HTO, pOutput_Info->timing.ht);
+		iic_write_ex(HAO, pOutput_Info->timing.ha);
+		iic_write_ex(HOO_HDMI, pOutput_Info->timing.ho);
+		iic_write_ex(HWO_HDMI, pOutput_Info->timing.hw);
+		iic_write_ex(VTO, pOutput_Info->timing.vt);
+		iic_write_ex(VAO, pOutput_Info->timing.va);
+		iic_write_ex(VOO_HDMI, pOutput_Info->timing.vo);
+		iic_write_ex(VWO_HDMI, pOutput_Info->timing.vw);
+
+		iic_write_ex(UCLK, pOutput_Info->uclk_khz);
+		iic_write_ex(ROTATE, pOutput_Info->rotate);
+		iic_write_ex(HFLIP, pOutput_Info->h_flip);
+		iic_write_ex(VFLIP, pOutput_Info->v_flip);
+		
+		hao_down = pOutput_Info->timing.ha * (100 - pOutput_Info->ds_percent_h) / 100;
+		hao_down = hao_down + (hao_down % 2);
+		vao_down = pOutput_Info->timing.va * (100 - pOutput_Info->ds_percent_v) / 100;
+		vao_down = vao_down + (vao_down % 2);
+		if(pOutput_Info->ds_percent_h || pOutput_Info->ds_percent_v)
+		{
+			iic_write_ex(SCAN_EN, 1);
+			iic_write_ex(HAO_SCL, hao_down);
+			iic_write_ex(VAO_SCL, vao_down);
+		}
+		
+		iic_write_ex(ROTATE, pOutput_Info->rotate);
+		iic_write_ex(HFLIP, pOutput_Info->h_flip);
+		iic_write_ex(VFLIP, pOutput_Info->v_flip);
+	}
+	
+	if(pOutput_Info->channel & CHANNEL_LVDS)
+	{
+		
+		lvds0_seq = (pLvdsFmt->channel_swap >>  0) & 0xF;
+		lvds1_seq = (pLvdsFmt->channel_swap >>  4) & 0xF;
+		lvds2_seq = (pLvdsFmt->channel_swap >>  8) & 0xF;
+		lvds3_seq = (pLvdsFmt->channel_swap >> 12) & 0xF;
+		lvdsclk_seq = (pLvdsFmt->channel_swap >>  16) & 0xF;
+		iic_write_ex(LVDS0_SEQ_SPP, lvds0_seq);
+		iic_write_ex(LVDS1_SEQ_SPP, lvds1_seq);
+		iic_write_ex(LVDS2_SEQ_SPP, lvds2_seq);
+		iic_write_ex(LVDS3_SEQ_SPP, lvds3_seq);
+		iic_write_ex(LVDSCLK_SEQ_SPP, lvdsclk_seq);
+		
+		lvds0_pol = (pLvdsFmt->channel_pol >> 0) & 0x1;
+		lvds1_pol = (pLvdsFmt->channel_pol >> 1) & 0x1;
+		lvds2_pol = (pLvdsFmt->channel_pol >> 2) & 0x1;
+		lvds3_pol = (pLvdsFmt->channel_pol >> 3) & 0x1;
+		lvdsclk_pol = (pLvdsFmt->channel_pol >> 4) & 0x1;
+		iic_write_ex(LVDS0_POL_SPP, lvds0_pol);
+		iic_write_ex(LVDS1_POL_SPP, lvds1_pol);
+		iic_write_ex(LVDS2_POL_SPP, lvds2_pol);
+		iic_write_ex(LVDS3_POL_SPP, lvds3_pol);
+		iic_write_ex(LVDSCLK_POL_SPP, lvdsclk_pol);
+		
+		
+		switch(pLvdsFmt->pixel_fmt){
+		  case 0:
+			 iic_write_ex(DITHER_SEL0_SPP, 0);
+		     iic_write_ex(DITHER_SEL1_SPP, 0);
+			 break;
+		  case 1:
+			 iic_write_ex(DITHER_SEL0_SPP, 1);
+		     iic_write_ex(DITHER_SEL1_SPP, 0);
+			 break;
+		  case 2:
+			 iic_write_ex(DITHER_SEL0_SPP, 0);
+		     iic_write_ex(DITHER_SEL1_SPP, 1);
+			 break;
+		  case 3:
+			 iic_write_ex(DITHER_SEL0_SPP, 1);
+		     iic_write_ex(DITHER_SEL1_SPP, 1);
+			 break;
+		  default:
+			iic_write_ex(DITHER_SEL0_SPP, 0);
+		    iic_write_ex(DITHER_SEL1_SPP, 0);
+			break;
+	    }
+
+	}
+	
+	if((pOutput_Info->channel & CHANNEL_VGA)&&((pOutput_Info->channel & CHANNEL_HDMI)==0x00))
+	{
+		
+
+		iic_write_ex(HPO_O, 1);
+		iic_write_ex(VPO_O, 1);
+		iic_write_ex(DEPO_O, 0);
+	}
+	else if((pOutput_Info->channel & CHANNEL_VGA)&&(pOutput_Info->channel & CHANNEL_HDMI))
+	{
+
+        iic_write_ex(HPO_O, 1);
+		iic_write_ex(VPO_O, 0);
+		iic_write_ex(DEPO_O, 0);
+	}
+
+	if((pOutput_Info->channel & CHANNEL_HDMI) && ((pOutput_Info->channel & CHANNEL_VGA) == 0x00))
+	{
+		 iic_write_ex(HDMIIN_HSP, pHdmiFmt->hs_pol ? 1:0);
+		 iic_write_ex(HDMIIN_VSP, pHdmiFmt->vs_pol ? 1:0);
+		 iic_write_ex(HDMIIN_DEP, 0);
+	}
+	if((pOutput_Info->channel & CHANNEL_HDMI)&&(pOutput_Info->channel & CHANNEL_VGA))
+	{
+		 iic_write_ex(HDMIIN_HSP, 0);
+		 iic_write_ex(HDMIIN_VSP, 1);
+		 iic_write_ex(HDMIIN_DEP, 1);
+	}
+
+	
+	if(pOutput_Info->channel & CHANNEL_HDMI)
+	{
+		
+		hd_dvib = pHdmiFmt->is_dvi_mode ? 0 : 1;
+		iic_write_ex(HD_DVIB, hd_dvib);
+		
+		switch(pHdmiFmt->format_index)
+		{
+		case  5:
+		case  6:
+		case  7:
+		case 10:
+		case 11:
+		case 20:
+		case 21:
+		case 22:
+		case 25:
+		case 26:
+			intlc = 1;
+			break;
+		default:
+			intlc = 0;
+			break;		
+		}
+		iic_write_ex(INTLC, intlc);
+		
+		copy = 1;
+		iic_write_ex(COPY, copy);
+		
+		hd_lv_pol = pHdmiFmt->data_pol_invert;
+		iic_write_ex(HD_LV_POL, hd_lv_pol);
+		
+		hd_lv_seq = pHdmiFmt->channel_swap;
+		iic_write_ex(HD_LV_SEQ, hd_lv_seq);
+		
+		hdmi_lvds_sel = 1;
+		iic_write_ex(HDMI_LVDS_SEL, hdmi_lvds_sel);
+		
+
+		if (pOutput_Info->timing.ha > 720) {
+			pOutput_Info->hdmi_fmt.hs_pol = POL_HIGH;
+			pOutput_Info->hdmi_fmt.vs_pol = POL_HIGH;
+			if(pOutput_Info->timing.ha == 1440)
+			{
+              pOutput_Info->hdmi_fmt.hs_pol = POL_LOW;
+			  pOutput_Info->hdmi_fmt.vs_pol = POL_LOW;
+			}
+		}
+		else {
+			
+			pOutput_Info->hdmi_fmt.hs_pol = POL_LOW;
+			pOutput_Info->hdmi_fmt.vs_pol = POL_LOW;
+		}
+
+		hsp = pHdmiFmt->hs_pol;
+		vsp = pHdmiFmt->vs_pol;
+		iic_write_ex(HSP, hsp);
+		iic_write_ex(VSP, vsp);
+		
+		
+		switch(pHdmiFmt->format_index)
+		{
+		case 1:
+		case 2:
+		case 17:
+			{
+				if(pHdmiFmt->aspect_ratio == AS_RATIO_16_9) 
+				{
+					g_nLastError = ERR_ASPECT_RATIO_NOMATCH;
+					return ch_false;
+				}
+			}
+			break;
+		case 4:
+		case 5:
+		case 16:
+		case 19:
+		case 20:
+		case 31:
+		case 32:
+		case 33:
+		case 34:
+			{
+				if(pHdmiFmt->aspect_ratio == AS_RATIO_4_3)	
+				{
+					g_nLastError = ERR_ASPECT_RATIO_NOMATCH;
+					return ch_false;
+				}
+			}
+			break;
+		default:
+			break;
+		}
+		m1m0 = pHdmiFmt->aspect_ratio;
+		iic_write_ex(M1M0, m1m0);
+		
+		c1c0 = 2;
+		iic_write_ex(C1C0, c1c0);
+		
+		vic = pHdmiFmt->format_index;
+		iic_write_ex(VIC, vic);
+	}
+
+	if(pOutput_Info->channel & CHANNEL_VGA){
+       intlc = 0;
+	}
+
+	iic_write_ex(INTLC, intlc);
+
+	
+	iic_write( 0x3,  0x1); 
+	iic_write( 0x23, 0x63); 
+	iic_write( 0x3,  0x0); 
+
+	return ch_true;
+}
+
+ch_bool set_prefer_info(PREFER_INFO* pPrefer_Info)
+{
+	uint8 hsync_cnt_th, prbs_set_sel;
+	uint8 dbp ;	
+	
+	iic_write_ex(MCLK, pPrefer_Info->mclk_khz);
+	
+	iic_write_ex(UCLKOD_SEL, pPrefer_Info->uclkod_sel);
+	iic_write_ex(DAT16_32B, pPrefer_Info->dat16_32b);
+	iic_write_ex(TRUE24, pPrefer_Info->true24);
+	iic_write_ex(TRUE_COM, pPrefer_Info->true_com);
+	
+	hsync_cnt_th = pPrefer_Info->lvds_out_hs_tolerance;
+	iic_write_ex(HSYNC_CNT_TH_SPP, hsync_cnt_th);
+	prbs_set_sel = pPrefer_Info->lvds_out_reset_bit_sel;
+	iic_write_ex(PRBS_SET_SEL_SPP, prbs_set_sel);
+	
+	dbp = pPrefer_Info->dither_filter_enable ? 0 : 1;
+	iic_write_ex(DBP, dbp);
+	
+
+
+	iic_write_ex(TXTEN, pPrefer_Info->text_enhancement);
+
+
+	
+
+
+
+	return ch_true;
+}
+
+
+ch_bool cal_and_set_clk_pll(DEV_CONTEXT* pDevContext)
+{
+	uint8 pll1n2_reg, pll1n2_div;
+	uint8 pll1n3_reg, pll1n3_div;
+	uint8 pll1n1_reg = 0, pll1n1_div = 0;
+	uint8 pll3n8_reg, pll3n8_div;
+	uint8 pll2n5_reg, pll2n5_div;
+	uint8 pll2n6_reg, pll2n6_div;
+	uint8 pll2n7_reg, pll2n7_div;
+	uint8 dmxtal_reg, dmxtal_div;
+	
+	uint32 a2_reg = 0;
+	uint32 a1_reg = 0;
+	uint32 a3_reg = 0;
+	uint32 uclk2d_reg = 0;
+	uint8 uclksec_reg = 0;
+	uint8 dri_pll_n1_reg;
+	uint8 dri_pll_n3_reg;
+	
+	uint32 val_t;
+	uint32 val_t1, val_t2;
+
+	uint8 gcksel = 0;
+	uint8 tsten1 = 0; 
+   	uint8 REV_ID;
+	uint64 temp1;
+
+	
+	INPUT_INFO* pInput_Info = pDevContext->pInput_Info;
+	OUTPUT_INFO* pOutput_Info = pDevContext->pOutput_Info;
+	PREFER_INFO* pPrefer_Info = pDevContext->pPrefer_Info;
+
+	I2CWrite(pDevContext,0x03, 0x04);
+	REV_ID = I2CRead(pDevContext,0x51) & 0x0F;
+
+	
+
+	if(pPrefer_Info->reset == 1) 
+	{
+      I2CWrite(pDevContext,0x03, 0x01);
+	  I2CWrite(pDevContext,0x14, I2CRead(pDevContext,0x14) | 0x40); 
+	  I2CWrite(pDevContext,0x03, 0x04);
+	  I2CWrite(pDevContext,0x54, I2CRead(pDevContext,0x54) | 0x40); 
+	  tsten1 = 0x40;
+	  gcksel = 0x40;
+	  iic_write_ex(GCKSEL, 1);
+	  iic_write_ex(TSTEN1, 1);
+	}
+	
+	
+	else if((pPrefer_Info->reset == 0) || (REV_ID >= 0x01)) 
+	{
+	  I2CWrite(pDevContext,0x03, 0x01);
+	  I2CWrite(pDevContext,0x14, I2CRead(pDevContext,0x14) & 0xBF); 
+	  I2CWrite(pDevContext,0x03, 0x04);
+	  I2CWrite(pDevContext,0x54, 0x40 | (I2CRead(pDevContext,0x54) & 0xBF)); 
+	  tsten1=0x00;
+	  gcksel=0x00;
+	  iic_write_ex(GCKSEL, 1);
+	  iic_write_ex(TSTEN1, 0);
+	}
+
+	
+	pll1n2_div = 4;
+	pll1n3_div = 8;
+	if(!convert_pll1n2_div(ch_false, &pll1n2_reg, &pll1n2_div))
+	{
+		g_nLastError = ERR_PLL1N2_WRONG;
+		return ch_false;
+	}
+	if(!convert_pll1n3_div(ch_false, &pll1n3_reg, &pll1n3_div))
+	{
+		g_nLastError = ERR_PLL1N3_WRONG;
+		return ch_false;
+	}
+	iic_write_ex(PLL1N2, pll1n2_reg);
+	iic_write_ex(PLL1N3, pll1n3_reg);
+
+	
+
+	if(((gcksel == 0x40)&&(tsten1 == 0x00)) || ((gcksel == 0x00)&&(tsten1 == 0x00)))
+	{
+       
+		
+		
+		
+			pll1n1_div = 8;
+		    pll1n1_reg = 3;
+		
+		
+        
+        
+		
+		
+	  
+	}
+	else if((gcksel == 0x40)&&(tsten1 == 0x40)){
+	  for(pll1n1_div=1; pll1n1_div<=64; pll1n1_div<<=1)
+	  {
+	 	val_t = pInput_Info->rx_clk_khz / pll1n1_div;
+	    if(val_t >= 2300 && val_t <= 4600)
+			break;
+	  }
+	  if(pll1n1_div > 64)
+	  {
+		g_nLastError = ERR_PLL1N1_WRONG;
+		return ch_false;
+	  }
+	  if(!convert_pll1n1_div(ch_false, &pll1n1_reg, &pll1n1_div))
+	  {
+		g_nLastError = ERR_PLL1N1_WRONG;
+		return ch_false;
+	  }
+	}
+
+	iic_write_ex(PLL1N1, pll1n1_reg);
+
+	
+	for(pll3n8_div=1; pll3n8_div<=8; pll3n8_div<<=1)
+	{
+		val_t = pPrefer_Info->mclk_khz * pll3n8_div / 64;
+		if(val_t >= 2300 && val_t <= 2600)
+			break;
+	}
+	if(pll3n8_div > 8)
+	{
+		g_nLastError = ERR_PLL3N8_WRONG;
+		return ch_false;
+	}
+	if(!convert_pll3n8_div(ch_false, &pll3n8_reg, &pll3n8_div))
+	{
+		g_nLastError = ERR_PLL3N8_WRONG;
+		return ch_false;
+	}
+	iic_write_ex(PLL3N8, pll3n8_reg);
+
+	
+
+	if((gcksel == 0x40)&&(tsten1 == 0x40)){
+		 val_t1 = (pInput_Info->rx_clk_khz << 12);
+		 val_t2 = (pll1n1_div * pll3n8_div * pPrefer_Info->mclk_khz);
+		 a2_reg = (val_t1 % val_t2) ? (val_t1 / val_t2 + 1) : (val_t1 / val_t2); 
+		  
+	}else if(((gcksel == 0x40)&&(tsten1 == 0x00))||((gcksel == 0x00)&&(tsten1 == 0x00))){
+	  val_t1 = (27000 << 12);
+	  val_t2 = (pll1n1_div * pll3n8_div * pPrefer_Info->mclk_khz);
+	  
+	 
+	
+	  
+	  a2_reg = (val_t1 % val_t2) ? (val_t1 / val_t2 + 1) : (val_t1 / val_t2); 
+	  if(pOutput_Info->uclk_khz == 148500){
+         a2_reg = 0x73;      
+	  }
+	}	
+
+	iic_write_ex(A2, a2_reg);
+
+	
+	if(pInput_Info->audio_type) 
+	{
+		uclksec_reg = pOutput_Info->uclk_khz / 10;
+	}
+	else 
+	{
+		
+
+		
+
+		 
+		if( (0x40==gcksel)&&(0x40==tsten1) )  
+		{
+			uclk2d_reg = (pInput_Info->rx_clk_khz * 2 * pll1n2_div * pll1n3_div) / (pll1n1_div * 10);
+		}
+		if(0x00==tsten1 )   
+		{
+			uclk2d_reg = (27000 * 2 * pll1n2_div * pll1n3_div) / (pll1n1_div * 10);
+		}
+
+	}
+	iic_write_ex(PCLK_NUM, uclk2d_reg);
+
+	
+
+	
+	
+	if((pOutput_Info->uclk_khz == 54000	||
+												  pOutput_Info->uclk_khz == 72000	||
+												  pOutput_Info->uclk_khz == 74250	||
+												  pOutput_Info->uclk_khz == 108000	||
+												  pOutput_Info->uclk_khz == 148500  ))
+	{
+		uclksec_reg = 1;
+	}
+	else
+	{
+		uclksec_reg = 0;
+	}
+	iic_write_ex(UCLKSEC, uclksec_reg);
+
+	
+	if(uclksec_reg == 0)
+	{
+		pll2n6_div = 8;
+		pll2n7_div = 8;
+		for(pll2n5_div=1; pll2n5_div<=8; ++pll2n5_div)
+		{
+			val_t = pOutput_Info->uclk_khz * pll2n5_div / 64;
+			if(val_t >= 2300 && val_t <= 4600)
+				break;
+		}
+		if(pll2n5_div > 8)
+		{
+			g_nLastError = ERR_PLL2N5_WRONG;
+			return ch_false;
+		}
+		dmxtal_div = 1; 
+		
+		if(pPrefer_Info->uclkod_sel == 1)
+		{
+			if((gcksel == 0x40)&&(tsten1 == 0x40)){
+				temp1 = (((uint64)pOutput_Info->uclk_khz) * pll1n1_div * pll2n5_div * (1 << 20));
+#ifdef T_LINUX
+	        	do_div(temp1 , pInput_Info->rx_clk_khz);
+				a1_reg = (uint32)temp1;
+#else
+				a1_reg = (uint32)((uint64)temp1 / pInput_Info->rx_clk_khz);
+#endif
+				PD_DEBUG ("#1 a1_reg = 0x%.8X\n", a1_reg);
+	      	} else if((gcksel == 0x40)&&(tsten1 == 0x00)){
+				temp1 = (((uint64)pOutput_Info->uclk_khz) * pll1n1_div * pll2n5_div * (1 << 20));
+#ifdef T_LINUX
+	        	do_div(temp1 , (uint32)27000);
+				a1_reg = (uint32)temp1;
+#else
+				a1_reg = (uint32)((uint64)temp1 / (uint32)27000);
+#endif
+				PD_DEBUG ("#2 a1_reg = 0x%.8X\n", a1_reg);
+	       	}else if((gcksel == 0x00)&&(tsten1 == 0x00)){
+				temp1 = (((uint64)pOutput_Info->uclk_khz) * pll1n1_div * pll2n5_div * (1 << 20));
+#ifdef T_LINUX
+	        	do_div(temp1 , (uint32)27000);
+				a1_reg = (uint32)temp1;
+#else
+				a1_reg = (uint32)((uint64)temp1 / (uint32)27000);
+#endif
+				PD_DEBUG ("#3 a1_reg = 0x%.8X\n", a1_reg);
+			}
+		   iic_write_ex(A1, a1_reg);
+		}
+		else
+		{
+			if((gcksel == 0x40)&&(tsten1 == 0x40))
+	       a3_reg = pInput_Info->rx_clk_khz * (1 << 12) / (pOutput_Info->uclk_khz * pll1n1_div * pll2n5_div);
+          else if((gcksel == 0x40)&&(tsten1 == 0x00))
+	       a3_reg = 27000 * (1 << 12) / (pOutput_Info->uclk_khz * pll1n1_div * pll2n5_div);
+          else if((gcksel == 0x00)&&(tsten1 == 0x00))
+	       a3_reg = 27000 * (1 << 12) / (pOutput_Info->uclk_khz * pll1n1_div * pll2n5_div);
+
+			iic_write_ex(A3, a3_reg);
+		}
+	}
+	else 
+	{
+		switch(pOutput_Info->uclk_khz)
+		{
+		case 54000:
+			dmxtal_div = 6;
+			pll2n7_div = 8;
+			pll2n6_div = 6;
+			pll2n5_div = 4;
+			break;
+		case 72000:
+			dmxtal_div = 6;
+			pll2n7_div = 8;
+			pll2n6_div = 6;
+			pll2n5_div = 3;
+			break;
+		case 74250:
+			dmxtal_div = 6;    
+			pll2n7_div = 11;
+			pll2n6_div = 6;    
+			pll2n5_div = 4;
+			break;
+		case 108000:
+			dmxtal_div = 6;
+			pll2n7_div = 8;
+			pll2n6_div = 6;
+			pll2n5_div = 2;
+			break;
+		case 148500:
+			
+			
+			
+			
+			dmxtal_div = 6;  
+			pll2n6_div = 6;  
+			
+            
+			
+			
+
+			pll2n7_div = 11;
+			pll2n5_div = 2;
+			break;
+		default:
+			return ch_false;
+		}
+	}
+	if(!convert_pll2n5_div(ch_false, &pll2n5_reg, &pll2n5_div))
+	{
+		g_nLastError = ERR_PLL2N5_WRONG;
+		return ch_false;
+	}
+	iic_write_ex(PLL2N5, pll2n5_reg & 0x07);
+	iic_write_ex(PLL2N53, pll2n5_reg >> 3 & 0x01);
+	if(!convert_pll2n6_div(ch_false, &pll2n6_reg, &pll2n6_div))
+	{
+		g_nLastError = ERR_PLL2N6_WRONG;
+		return ch_false;
+	}
+	iic_write_ex(PLL2N6, pll2n6_reg);
+	if(!convert_pll2n7_div(ch_false, &pll2n7_reg, &pll2n7_div))
+	{
+		g_nLastError = ERR_PLL2N7_WRONG;
+		return ch_false;
+	}
+	iic_write_ex(PLL2N7, pll2n7_reg);
+	if(!convert_dmxtal_div(ch_false, &dmxtal_reg, &dmxtal_div))
+	{
+		g_nLastError = ERR_DMXTAL_WRONG;
+		return ch_false;
+	}
+	iic_write_ex(DIVXTAL, dmxtal_reg);
+
+	
+	if(pInput_Info->rx_clk_khz > 40000)
+	{
+		iic_write_ex(TXPLL_FFD, 1);
+	}
+
+	
+	if(pOutput_Info->channel & CHANNEL_HDMI)
+	{
+		val_t = pOutput_Info->uclk_khz;
+		if(val_t < 25000 || val_t > 165000)
+		{
+			g_nLastError = ERR_HDMI_CLOCK_NO_SUPPORT;
+			return ch_false;
+		}
+		if(val_t <= 40000)
+		{
+			dri_pll_n1_reg = 0;
+			dri_pll_n3_reg = 0;
+		}
+		else if(val_t < 80000)
+		{
+			dri_pll_n1_reg = 1;
+			dri_pll_n3_reg = 1;
+		}
+		else
+		{
+			dri_pll_n1_reg = 2;
+			dri_pll_n3_reg = 2;
+		}
+		iic_write_ex(DRI_PLL_N1, dri_pll_n1_reg);
+		iic_write_ex(DRI_PLL_N3, dri_pll_n3_reg);
+	}
+
+	
+	iic_write_ex(CK_TVINV, 1);
+	
+	return ch_true;
+}
+
+ch_bool cal_and_set_scaler(DEV_CONTEXT* pDevContext)
+{
+	uint8 wrlen_reg;
+	uint32 frame_rate_in, frame_rate_out, field_rate_out;
+	uint32 hai_down, hai_sdram;
+	uint8 fltbp2_reg, fltbp1_reg;
+	uint8 dnsmpen_reg;
+	uint32 hadwn_reg = 0;
+	uint8 blk_h_reg;
+	uint32 fba_inc_reg;
+	uint8 sfm_reg;
+	uint8 thren_reg;
+	uint32 thrrl_reg;
+	uint8 lnsel_reg;
+	uint8 wrfast_reg;
+	uint8 chg_hl_reg;
+	uint8 vsmst_reg;
+
+	uint32 val_t;
+	uint32 hao_t;
+	uint32 vao_t;
+	uint32 vai_t;
+
+	
+	INPUT_INFO* pInput_Info = pDevContext->pInput_Info;
+	OUTPUT_INFO* pOutput_Info = pDevContext->pOutput_Info;
+	PREFER_INFO* pPrefer_Info = pDevContext->pPrefer_Info;
+
+	
+	wrlen_reg = 0;
+	iic_write_ex(WRLEN, wrlen_reg);
+
+	
+	frame_rate_in = ((pInput_Info->rx_clk_khz * 10000) / pInput_Info->timing.ht) * 10 / pInput_Info->timing.vt;
+	frame_rate_out = ((pOutput_Info->uclk_khz * 10000) / pOutput_Info->timing.ht) * 10 / pOutput_Info->timing.vt;
+	field_rate_out = iic_read_ex(INTLC) ? (frame_rate_out * 2) : (frame_rate_out);
+
+	
+	hai_down = pInput_Info->timing.ha;
+	if(pOutput_Info->ds_percent_h)
+	{
+		hao_t = pOutput_Info->timing.ha * (100 - pOutput_Info->ds_percent_h) / 100;
+	}
+	else
+	{
+		hao_t = pOutput_Info->timing.ha;
+	}
+	hao_t = hao_t + (hao_t % 2);
+	if(hai_down > hao_t)
+	{
+		dnsmpen_reg = 1;
+		hadwn_reg = hao_t;
+		hai_down = hadwn_reg;
+		fltbp2_reg = 1;
+		fltbp1_reg = 1;
+	}
+	else
+	{
+		dnsmpen_reg = 0;
+		fltbp2_reg = 1;
+		fltbp1_reg = 1;
+	}
+	if(pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270)
+	{
+		val_t = 720;
+	}
+	else
+	{
+		if(pPrefer_Info->dat16_32b)
+		{
+			val_t = 720;
+		}
+		else
+		{
+			val_t = pPrefer_Info->true24 ? 720 : 1440;
+		}
+	}
+	if(hai_down > val_t && (pOutput_Info->rotate != ROTATE_NO || pOutput_Info->h_flip || pOutput_Info->v_flip))
+	{
+		dnsmpen_reg = 1;
+		hadwn_reg = val_t;
+		hai_down = hadwn_reg;
+		fltbp2_reg = 1;
+		fltbp1_reg = 1;
+	}
+	iic_write_ex(DNSMPEN, dnsmpen_reg);
+	iic_write_ex(HADWSPP, hadwn_reg);
+	
+	if(pInput_Info->timing.ha * 100 / hao_t > pPrefer_Info->hscale_ratio_gate)
+	{
+		fltbp1_reg = 0;
+	}
+	iic_write_ex(FLTBP2, fltbp2_reg);
+	iic_write_ex(FLTBP1, fltbp1_reg);
+
+	
+	if(pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270)
+	{
+		val_t = 100;
+	}
+	else
+	{
+		if(pPrefer_Info->dat16_32b)
+		{
+			val_t = 100;
+		}
+		else if(pPrefer_Info->true24)
+		{
+			val_t = 100;
+		}
+		else
+		{
+			val_t = pPrefer_Info->true_com ? 75 : 50;
+		}
+	}
+	if(val_t == 75)
+	{
+		hai_sdram = (hai_down / 4) * 3 + (hai_down % 4);
+	}
+	else
+	{
+		hai_sdram = hai_down * val_t / 100;
+	}
+	if(pOutput_Info->rotate != ROTATE_NO || pOutput_Info->h_flip || pOutput_Info->v_flip)
+	{
+		blk_h_reg = 45;
+	}
+	else if(hai_sdram <= 720 && pInput_Info->timing.va <= 720)
+	{
+		blk_h_reg = 45;
+	}
+	else
+	{
+		blk_h_reg = hai_sdram / 16;
+		blk_h_reg = (hai_sdram % 16) ? (blk_h_reg + 1) : blk_h_reg;
+	}
+	iic_write_ex(BLK_H, blk_h_reg);
+
+	
+	if((pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270) && pPrefer_Info->true24 == 0 && pPrefer_Info->true_com == 0 && pPrefer_Info->dat16_32b == 0)
+	{
+		vai_t = pInput_Info->timing.va / 2;
+	}
+	else
+	{
+		vai_t = pInput_Info->timing.va;
+	}
+	val_t = (vai_t % 16) ? (vai_t / 16 + 1) : (vai_t / 16);
+	fba_inc_reg = blk_h_reg * val_t;
+	if(fba_inc_reg > 2048)
+	{
+		sfm_reg = 1;
+		thren_reg = 1;
+		val_t = (frame_rate_in * 100) / field_rate_out;
+		if(val_t > 100)
+		{
+			
+			
+			thrrl_reg = pInput_Info->timing.vt * (100 - 10000 / val_t) / 100 + THRRL_ADJUST_DEF;
+		}
+		else
+		{
+			thrrl_reg = pInput_Info->timing.vt * (100 - val_t) / 100 + THRRL_ADJUST_DEF;
+		}
+	}
+	else
+	{
+		sfm_reg = 0;
+		thren_reg = 0;
+		thrrl_reg = 0;
+	}
+	iic_write_ex(FBA_INC, fba_inc_reg);
+	iic_write_ex(SFM, sfm_reg);
+	iic_write_ex(THREN, thren_reg);
+	iic_write_ex(THRRL, thrrl_reg);
+
+	
+	if(pOutput_Info->ds_percent_v)
+	{
+		vao_t = pOutput_Info->timing.va * (100 - pOutput_Info->ds_percent_v) / 100;
+	}
+	else
+	{
+		vao_t = pOutput_Info->timing.va;
+	}
+	vao_t = vao_t + (vao_t % 2);
+	val_t = iic_read_ex(INTLC) ? (vao_t / 2) : vao_t;
+	if(pOutput_Info->rotate == ROTATE_90 || pOutput_Info->rotate == ROTATE_270)
+	{
+		if(hai_down <= val_t)
+			lnsel_reg = 3;
+		else
+			lnsel_reg = 1;
+	}
+	else
+	{
+		if(pInput_Info->timing.va <= val_t)
+			lnsel_reg = 3;
+		else
+			lnsel_reg = 1;
+	}
+	if(pPrefer_Info->scale_line_adjust)
+	{
+		lnsel_reg++;
+		if((pOutput_Info->ds_percent_v >= 2) && (pOutput_Info->ds_percent_v <= 12) &&
+            (pOutput_Info->ds_percent_h <= 12) &&
+
+			(pOutput_Info->channel & CHANNEL_VGA) &&
+			(pOutput_Info->timing.ha == 1280) && (pOutput_Info->timing.va == 960) &&
+			(pOutput_Info->timing.hz == 60) && (pInput_Info->rx_clk_khz >= 75428)&&
+			(pInput_Info->timing.ha == 1280) && (pInput_Info->timing.va == 1024)&&
+			(pInput_Info->timing.hz >= 49)){
+			
+				lnsel_reg++;		
+
+		}
+
+		
+
+
+		if((pOutput_Info->ds_percent_v >= 2) && (pOutput_Info->ds_percent_v <= 12) &&
+            (pOutput_Info->ds_percent_h >= 0) && (pOutput_Info->ds_percent_h <= 12) &&
+			(pOutput_Info->channel & CHANNEL_VGA) &&
+			(pOutput_Info->timing.ha == 1280) && (pOutput_Info->timing.va == 1024) &&
+			(pOutput_Info->timing.hz == 60) && (pInput_Info->rx_clk_khz >= 75428)){
+			
+				lnsel_reg++;		
+
+		}
+
+		if((pOutput_Info->ds_percent_v >= 2 ) && 
+            (pOutput_Info->ds_percent_h >= 2 ) && (pOutput_Info->channel & CHANNEL_VGA) &&
+			(pOutput_Info->timing.ha == 1280) && (pOutput_Info->timing.va == 1024) &&
+			(pOutput_Info->timing.hz == 75) && (pInput_Info->rx_clk_khz >= 75428)){
+			
+				lnsel_reg++;
+		}
+
+		if((pOutput_Info->ds_percent_v >= 6 ) && 
+            (pOutput_Info->ds_percent_h >= 6 ) && (pOutput_Info->channel & CHANNEL_HDMI) &&
+			(pOutput_Info->timing.ha == 1920) && (pOutput_Info->timing.va == 1080) &&
+			(pOutput_Info->timing.hz == 50) && (pInput_Info->rx_clk_khz >= 75428)){
+			
+				lnsel_reg++;
+		}
+		if((pOutput_Info->ds_percent_v >= 6 ) && 
+            (pOutput_Info->ds_percent_h >= 6 ) && (pOutput_Info->channel & CHANNEL_HDMI) &&
+			(pOutput_Info->timing.ha == 1920) && (pOutput_Info->timing.va == 1080) &&
+			(pOutput_Info->timing.hz == 59) && (pInput_Info->rx_clk_khz >= 75428)){
+			
+				lnsel_reg++;
+		}
+		if((pOutput_Info->ds_percent_v >= 6 ) && 
+            (pOutput_Info->ds_percent_h >= 6 ) && (pOutput_Info->channel & CHANNEL_HDMI) &&
+			(pOutput_Info->timing.ha == 1920) && (pOutput_Info->timing.va == 1080) &&
+			(pOutput_Info->timing.hz == 60) && (pInput_Info->rx_clk_khz >= 75428)){
+			
+				lnsel_reg++;
+		}
+	}
+	iic_write_ex(LNSEL, lnsel_reg);
+
+	
+	if(frame_rate_in >= field_rate_out)
+		wrfast_reg = 1;
+	else
+		wrfast_reg = 0;
+	iic_write_ex(WRFAST, wrfast_reg);
+
+	
+	chg_hl_reg = (	( 		(pPrefer_Info->dat16_32b == 0)		&&
+					(pPrefer_Info->true24 == 0)		&&
+					(pPrefer_Info->true_com == 0)		&&
+				(	(pOutput_Info->rotate == 0)		&&
+					(pOutput_Info->h_flip == 1)	) )	||
+				(	(pOutput_Info->rotate == 1)		&&
+					(pOutput_Info->h_flip == 0)	)	||
+				(	(pOutput_Info->rotate == 3) 		&&
+					(pOutput_Info->h_flip == 1) 	)	||
+				(	(pOutput_Info->rotate == 2) 		&&
+					(pOutput_Info->h_flip == 0)  )   ) 	? 1 : 0;
+	iic_write_ex(CHG_HL, chg_hl_reg);
+
+	
+	vsmst_reg = 2;
+	iic_write_ex(VSMST, vsmst_reg);
+
+	return ch_true;	
+}
+
+ch_bool post_cal_and_set(DEV_CONTEXT* pDevContext)
+{
+	uint32 hdinc_reg, hdinca_reg, hdincb_reg;
+	uint32 hinc_reg, hinca_reg, hincb_reg;
+	uint32 vinc_reg, vinca_reg, vincb_reg;
+
+	uint32 val_t;
+	uint64 temp1;
+	
+
+	
+	I2CWrite(pDevContext,0x03, 0x04);
+	
+	val_t = I2CRead(pDevContext,0x2A);
+	hinca_reg = (val_t << 3) | (I2CRead(pDevContext,0x2B) & 0x07);
+	
+	val_t = I2CRead(pDevContext,0x2C);
+	hincb_reg = (val_t << 3) | (I2CRead(pDevContext,0x2D) & 0x07);
+	
+	val_t = I2CRead(pDevContext,0x2E);
+	vinca_reg = (val_t << 3) | (I2CRead(pDevContext,0x2F) & 0x07);
+	
+	val_t = I2CRead(pDevContext,0x30);
+	vincb_reg = (val_t << 3) | (I2CRead(pDevContext,0x31) & 0x07);
+	
+	val_t = I2CRead(pDevContext,0x32); 
+	hdinca_reg = (val_t << 3) | (I2CRead(pDevContext,0x33) & 0x07);
+	
+	val_t = I2CRead(pDevContext,0x34);
+	hdincb_reg = (val_t << 3) | (I2CRead(pDevContext,0x35) & 0x07);
+
+	
+	I2CWrite(pDevContext,0x03, 0x04);
+
+	
+	if(iic_read_ex(DNSMPEN))
+	{
+		if(hdincb_reg == 0)
+		{
+			g_nLastError = ERR_CAL_INC_DIV_ZERO;
+			return ch_false;
+		}
+		temp1 = ((uint64)hdinca_reg) * (1 << 20);
+#ifdef T_LINUX
+		do_div(temp1 , hdincb_reg);
+		hdinc_reg = (uint32)temp1;
+#else
+		hdinc_reg = (uint32)((uint64)temp1  / hdincb_reg);
+#endif
+		
+
+		PD_DEBUG ("#1 hdinc_reg = 0x%.8X\n", hdinc_reg);
+		I2CWrite(pDevContext,0x3C, (hdinc_reg >> 16) & 0xFF);
+		I2CWrite(pDevContext,0x3D, (hdinc_reg >>  8) & 0xFF);
+		I2CWrite(pDevContext,0x3E, (hdinc_reg >>  0) & 0xFF);
+	}
+	if(hincb_reg == 0 || vincb_reg == 0)
+	{
+		g_nLastError = ERR_CAL_INC_DIV_ZERO;
+		return ch_false;
+	}
+	
+	if(hinca_reg > hincb_reg)
+	{
+		g_nLastError = ERR_CAL_INC_NO_MATH;
+		return ch_false;
+	}
+
+	temp1 = (uint64)hinca_reg * (1 << 20);
+#ifdef T_LINUX
+	do_div(temp1 , hincb_reg);
+	hinc_reg = (uint32)temp1;
+#else
+	hinc_reg = (uint32)((uint64)temp1 / hincb_reg);
+#endif
+	
+PD_DEBUG ("#2 hinc_reg = 0x%.8X\n", hinc_reg);
+
+	temp1 = (uint64)vinca_reg * (1 << 20);
+#ifdef T_LINUX
+	do_div( temp1 , vincb_reg);
+	vinc_reg = (uint32)temp1;
+#else
+	vinc_reg = (uint32)((uint64)temp1 / vincb_reg);
+#endif
+	
+	PD_DEBUG ("#1 vinc_reg = 0x%.8X\n", vinc_reg);
+	
+	I2CWrite(pDevContext,0x36, (hinc_reg >> 16) & 0xFF);
+	I2CWrite(pDevContext,0x37, (hinc_reg >>  8) & 0xFF);
+	I2CWrite(pDevContext,0x38, (hinc_reg >>  0) & 0xFF);
+
+	I2CWrite(pDevContext,0x39, (vinc_reg >> 16) & 0xFF);
+	I2CWrite(pDevContext,0x3A, (vinc_reg >>  8) & 0xFF);
+	I2CWrite(pDevContext,0x3B, (vinc_reg >>  0) & 0xFF);
+
+	return ch_true;
+}
+
+
+
+
+
+
+ch_bool cal_and_set_power(DEV_CONTEXT* pDevContext)
+{
+	
+	uint8 hdmi_pd = 1;
+	uint8 i2s_pd = 1;
+	uint8 spdif_pd = 1;
+	uint8 auddac=1;
+	uint8 dri_pd = 1;
+	uint8 dri_pd_ser = 1;
+	uint8 dri_pd_pll = 1;
+	uint8 dri_pddri = 7;
+	uint8 cec_pd = 1; 
+	uint8 pd_ddc = 1;
+
+	
+	uint8 lvds_pd = 1;
+	uint8 rx_pd = 63;
+	uint8 rxpll_pd = 1;
+	uint8 txpll_pd = 1;
+	uint8 txdrv_pd = 1;
+	uint8 txser_pd = 1;
+
+	
+	
+
+
+	uint8 icen0 =1;		
+	
+
+	
+	uint8 vga_pd = 1;
+	uint8 pddac = 7;
+
+	uint8 pdpll1 = 1;
+	uint8 pdpll0 = 1;
+
+
+	uint8 pd_prom = 0; 
+	uint8 pdmio = 1;
+	uint8 pdio = 1;
+	uint8 hpd_pd = 0; 
+
+	
+	uint8 sclpd = 1;
+	uint8 sdpd = 1;
+	uint8 mempd = 1;
+	uint8 dacsence = 1;
+
+	uint8 gckoff = 0; 
+
+	
+	uint8 dispon = 0;
+
+
+
+
+	
+	INPUT_INFO* pInput_Info = pDevContext->pInput_Info;
+	OUTPUT_INFO* pOutput_Info = pDevContext->pOutput_Info;
+	PREFER_INFO* pPrefer_Info = pDevContext->pPrefer_Info;
+
+	
+	iic_write_ex(CRYS_FREQ_SPP, 27000);
+	iic_write_ex(I2SCK_SEC, 1);
+	iic_write_ex(SP_EN, 0);
+	iic_write_ex(HARD_SOFTB, 1);
+	iic_write_ex(MULT_I2CEN, 0);
+
+	
+	
+	if(pOutput_Info->channel & CHANNEL_LVDS)
+	{
+		lvds_pd = 0;
+		rx_pd = 0;
+		rxpll_pd = 0;
+		txpll_pd = 0;
+		txdrv_pd = 0;
+		txser_pd = 0;
+		pdio = 0; 
+	
+
+	}
+	if(pOutput_Info->channel & CHANNEL_HDMI)
+	{
+		hdmi_pd = 0;
+		if(pInput_Info->audio_type == 1)
+			i2s_pd = 0;
+		else {
+			spdif_pd = 0;
+			auddac=0;
+		}
+		dri_pd = 0;
+		dri_pddri = 0;
+		dri_pd_ser = 0;
+		dri_pd_pll = 0;		
+		pd_ddc = 0;
+		
+		vga_pd = 0;
+		pdmio = 0;
+		sclpd = 0;
+		sdpd = 0;
+		gckoff = 0;
+		mempd = 0;
+
+		rx_pd = 0; 
+		rxpll_pd = 0;
+		
+		pdpll0 = 0;
+		pdpll1 = 0;
+		icen0 =0;		
+		pdio = 0;
+
+		hpd_pd = 0;
+		
+	}
+	if(pOutput_Info->channel & CHANNEL_VGA)
+	{
+		vga_pd = 0;
+		pdmio = 0;	
+		sclpd = 0;
+		sdpd = 0;
+		gckoff = 0;
+		mempd = 0;
+		
+		rx_pd = 0;
+		rxpll_pd = 0;	
+		
+		pdpll0 = 0;
+		pdpll1 = 0;
+		icen0 =0;
+		pdio = 0;
+
+		dispon = 1;
+		dri_pd_pll = 0;
+				
+		dacsence=1;		
+		pddac = 0;
+	}else{
+		
+		
+
+		if(pPrefer_Info->vga_enable)
+           dispon = 0;
+	}
+
+	
+	iic_write_ex(HDMI_PD,		hdmi_pd);
+	iic_write_ex(I2S_PD,		i2s_pd);
+	iic_write_ex(SPDIF_PD,		spdif_pd);
+
+	iic_write_ex(AUDDAC,        auddac);
+
+	iic_write_ex(DRI_PD,		dri_pd);
+	iic_write_ex(DRI_PD_SER,	dri_pd_ser);
+	iic_write_ex(DRI_PD_PLL,	dri_pd_pll);
+	iic_write_ex(DRI_PDDRI,		dri_pddri);
+	iic_write_ex(CEC_PD,		cec_pd);
+	iic_write_ex(PD_DDC,		pd_ddc);
+	iic_write_ex(LVDS_PD,		lvds_pd);
+	iic_write_ex(RX_PD,			rx_pd);
+	iic_write_ex(RXPLL_PD,		rxpll_pd);
+	iic_write_ex(TXPLL_PD,		txpll_pd);
+	iic_write_ex(TXDRV_PD,		txdrv_pd);
+	iic_write_ex(TXSER_PD,		txser_pd);
+	iic_write_ex(VGA_PD,		vga_pd);
+	iic_write_ex(PDDAC,			pddac);
+	iic_write_ex(PDPLL1,		pdpll1);
+	iic_write_ex(PDPLL0,		pdpll0);
+	iic_write_ex(ICEN0,			icen0);
+	iic_write_ex(PD_PROM,		pd_prom);
+	iic_write_ex(PDMIO,			pdmio);
+	iic_write_ex(PDIO,			pdio);
+	iic_write_ex(HPD_PD,		hpd_pd);
+	iic_write_ex(SCLPD,			sclpd);
+	iic_write_ex(SDPD,			sdpd);
+	iic_write_ex(MEMPD,			mempd);
+	iic_write_ex(DISPON,		dispon);
+	
+	iic_write_ex(DACSENCE,			dacsence);	
+	iic_write_ex(GCKOFF,			gckoff);
+	iic_write_ex(ZRCTS, 0);
+
+	return ch_true;
+}
+
+ch_bool convert_pll1n1_div(ch_bool pll1n1_to_div, uint8* pll1n1_addr, uint8* div_addr)
+{
+	uint8 val_t;
+
+	if(pll1n1_to_div)	
+	{
+		if((*pll1n1_addr) <= 5)
+		{
+			(*div_addr)= 1<<(*pll1n1_addr);
+		}
+		else if((*pll1n1_addr) == 6 || (*pll1n1_addr) == 7) 
+		{
+			(*div_addr) = 64;
+		}
+		else
+		{
+			return ch_false;
+		}
+	}
+	else 
+	{
+		for(val_t=1; val_t<=6; ++val_t)
+		{
+			if(*div_addr == (1 << val_t))
+			{
+				*pll1n1_addr = val_t;
+				return ch_true;
+			}
+		}
+		return ch_false;
+	}
+	return ch_true;
+}
+
+ch_bool convert_pll1n2_div(ch_bool pll1n2_to_div, uint8* pll1n2_addr, uint8* div_addr)
+{
+	uint8 val_t;
+
+	if(pll1n2_to_div)	
+	{
+		if((*pll1n2_addr) <= 3)
+		{
+			*div_addr = 1 << (*pll1n2_addr);
+		}
+		else if((4 == (*pll1n2_addr)) || (6 == (*pll1n2_addr)))
+		{
+			(*div_addr) = 16;
+		}
+		else if((5 == (*pll1n2_addr)) || (7 == (*pll1n2_addr)))
+		{
+			(*div_addr) = 32;
+		} 
+		else 
+		{
+			return ch_false;
+		}
+	}
+	else	
+	{
+		for(val_t=0; val_t<=5; ++val_t)
+		{
+			if(*div_addr == (1 << val_t))
+			{
+				*pll1n2_addr = val_t;
+				return ch_true;
+			}
+		}
+		return ch_false;
+	}
+	return ch_true;
+}
+
+ch_bool convert_pll1n3_div(ch_bool pll1n3_to_div, uint8* pll1n3_addr, uint8* div_addr)
+{
+	uint8 val_t;
+	
+	if(pll1n3_to_div)	
+	{
+		if((*pll1n3_addr) <= 3)
+		{
+			*div_addr = 1 << (*pll1n3_addr);
+		}
+		else if((4 == (*pll1n3_addr)) || (6 == (*pll1n3_addr)))
+		{
+			(*div_addr) = 16;
+		}
+		else if((5 == (*pll1n3_addr)) || (7 == (*pll1n3_addr)))
+		{
+			(*div_addr) = 32;
+		} 
+		else 
+		{
+			return ch_false;
+		}
+	}
+	else	
+	{
+		for(val_t=0; val_t<=5; ++val_t)
+		{
+			if(*div_addr == (1 << val_t))
+			{
+				*pll1n3_addr = val_t;
+				return ch_true;
+			}
+		}
+		return ch_false;
+	}
+	return ch_true;
+}
+
+ch_bool convert_pll2n5_div(ch_bool pll2n5_to_div, uint8* pll2n5_addr, uint8* div_addr)
+{
+	if(pll2n5_to_div)	
+	{
+		switch(*pll2n5_addr)
+		{
+		case 0:		
+			*div_addr = 1;	
+			break;
+		case 4:		
+			*div_addr = 2;	
+			break;
+		case 1:    
+			*div_addr = 3;
+			break;
+		case 8:    
+			*div_addr = 4;
+			break;
+		case 2:    
+			*div_addr = 5;
+			break;
+		case 5:    
+			*div_addr = 6;
+			break;
+		case 3:    
+			*div_addr = 7;
+			break;
+		case 12:
+			*div_addr = 8;
+			break;
+		default :
+			return ch_false;
+		}
+	}
+	else	
+	{
+		switch(*div_addr)
+		{
+		case 1:    
+			*pll2n5_addr = 0;
+			break;
+		case 2:    
+			*pll2n5_addr = 4;
+			break;
+		case 3:    
+			*pll2n5_addr = 1;
+			break;
+		case 4:    
+			*pll2n5_addr = 8;
+			break;
+		case 5:    
+			*pll2n5_addr = 2;
+			break;
+		case 6:    
+			*pll2n5_addr = 5;
+			break;
+		case 7:    
+			*pll2n5_addr = 3;
+			break;
+		case 8:    
+			*pll2n5_addr = 0x0C;
+			break;
+		default : 
+			return ch_false;
+		}
+	}
+	return ch_true;
+}
+
+ch_bool convert_pll2n6_div(ch_bool pll2n6_to_div, uint8* pll2n6_addr, uint8* div_addr)
+{
+	if(pll2n6_to_div)
+	{
+		if(*pll2n6_addr <= 3)
+		{
+			(*div_addr)= (*pll2n6_addr) + 5;
+			return ch_true;
+		}
+		return ch_false;
+	}
+	else
+	{
+		if(*div_addr >= 5 && *div_addr <= 8)
+		{
+			*pll2n6_addr = (*div_addr) - 5;
+			return ch_true;
+		}
+		return ch_false;
+	}
+	return ch_true;
+}
+
+ch_bool convert_pll2n7_div(ch_bool pll2n7_to_div, uint8* pll2n7_addr, uint8* div_addr)
+{
+	if(pll2n7_to_div)
+	{
+		if(*pll2n7_addr <= 3)
+		{
+			(*div_addr)= (*pll2n7_addr) + 8;
+			return ch_true;
+		}
+		return ch_false;
+	}
+	else
+	{
+		if(*div_addr >= 8 && *div_addr <= 11)
+		{
+			*pll2n7_addr = (*div_addr) - 8;
+			return ch_true;
+		}
+		return ch_false;
+	}
+	return ch_true;
+}
+
+ch_bool convert_pll3n8_div(ch_bool pll3n8_to_div, uint8* pll3n8_addr, uint8* div_addr)
+{
+	uint8 val_t;
+
+	if(pll3n8_to_div)	
+	{
+		if(*pll3n8_addr <= 3)
+		{
+			*div_addr= 1 << (*pll3n8_addr);
+			return ch_true;
+		}
+		return ch_false;
+	}
+	else	
+	{
+		for(val_t=0; val_t<=3; ++val_t)
+		{
+			if(*div_addr == (1 << val_t))
+			{
+				*pll3n8_addr = val_t;
+				return ch_true;
+			}
+		}
+        return ch_false;
+	}
+
+	return ch_true;
+}
+
+ch_bool convert_dmxtal_div(ch_bool dmxtal_to_div, uint8* dmxtal_addr, uint8* div_addr)
+{
+	if(dmxtal_to_div)	
+	{
+		switch(*dmxtal_addr)
+		{
+		case 0x00:  
+			*div_addr = 1;
+			break;
+		case 0x04: 
+			*div_addr = 2;
+			break;
+		case 0x08: 
+			*div_addr = 3;
+			break;
+		case 0x0C:  
+			*div_addr = 4;
+			break;
+		case 0x10: 
+			*div_addr = 5;
+			break;
+		case 0x11: 
+			*div_addr = 6;
+			break;
+		case 0x12: 
+			*div_addr = 7;
+			break;
+		case 0x13: 
+			*div_addr = 8;
+			break;
+		case 0x01: 
+			*div_addr = 9;
+			break;
+		case 0x14: 
+			*div_addr = 10;
+			break;
+		case 0x02: 
+			*div_addr = 11;
+			break;
+		case 0x15: 
+			*div_addr = 12;
+			break;
+		case 0x03: 
+			*div_addr = 13;
+			break;
+		case 0x16: 
+			*div_addr = 14;
+			break;
+		case 0x18: 
+			*div_addr = 15;
+			break;
+		case 0x17: 
+			*div_addr = 16;
+			break;
+		default:  
+			return ch_false;
+		}
+	}
+	else	
+	{
+		switch(*div_addr)
+		{
+		case 1:  
+			*dmxtal_addr = 0x00;
+			break;
+		case 2: 
+			*dmxtal_addr = 0x04;
+			break;
+		case 3: 
+			*dmxtal_addr = 0x08;
+			break;
+		case 4: 
+			*dmxtal_addr = 0x0C;
+			break;
+		case 5:
+			*dmxtal_addr = 0x10;
+			break;
+		case  6: 
+			*dmxtal_addr = 0x11;
+			break;
+		case 7: 
+			*dmxtal_addr = 0x12;
+			break;
+		case 8: 
+			*dmxtal_addr = 0x13;
+			break;
+		case 9: 
+			*dmxtal_addr = 0x01;
+			break;
+		case 10: 
+			*dmxtal_addr = 0x14;
+			break;
+		case 11: 
+			*dmxtal_addr = 0x02;
+			break;
+		case 12: 
+			*dmxtal_addr = 0x15;
+			break;
+		case 13: 
+			*dmxtal_addr = 0x03;
+			break;
+		case 14: 
+			*dmxtal_addr = 0x16;
+			break;
+		case 15:
+			*dmxtal_addr = 0x18;
+			break;
+		case 16: 
+			*dmxtal_addr = 0x17;
+			break;
+		default: 
+			return ch_false;
+		}
+	}
+	return ch_true;
+}
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.def b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.def
new file mode 100644
index 0000000..49af6a5
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.def
@@ -0,0 +1,5 @@
+LIBRARY ch7036
+
+EXPORTS
+    get_version
+    dpd_init
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.h
new file mode 100755
index 0000000..9452854
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036.h
@@ -0,0 +1,51 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file  ch7036.h
+* @version 1.2.2
+*-----------------------------------------------------------------------------
+*/
+
+#ifndef _CH7036_H
+#define _CH7036_H
+
+#include "ch7036_typedef.h"
+
+
+
+ch_bool DevicePrepare(DEV_CONTEXT* pDevContext);
+	
+
+ch_bool DeviceConfig(DEV_CONTEXT* pDevContext);
+
+
+ch_bool DeviceRunning(DEV_CONTEXT* pDevContext);
+
+
+ch_bool DeviceSetPower(DEV_CONTEXT* pDevContext, unsigned long flags);
+
+
+uint32 GetLastErrorMessage(void);
+
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.c
new file mode 100644
index 0000000..fb5cdfe
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.c
@@ -0,0 +1,1061 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file  ch7036_attr.c
+* @version 1.2.5
+*-----------------------------------------------------------------------------
+*/
+ 
+
+
+
+#include "ch7036_intf.h"
+#include "ch7036_attr.h"
+
+
+#ifdef T_LINUX
+	#include "lvds/lvds.h"
+#else
+	#include "lvds.h"
+#endif
+
+
+
+static pd_attr_t g_ch7036_attrs[] =
+{
+	
+
+	
+	PD_MAKE_ATTR (PD_ATTR_ID_HPOSITION,   PD_ATTR_TYPE_RANGE, "H Pos.",  0, DEFAULT_POSITION,	DEFAULT_POSITION,                    DEFAULT_POSITION - 40,  DEFAULT_POSITION + 40,  1),
+	PD_MAKE_ATTR (PD_ATTR_ID_VPOSITION,   PD_ATTR_TYPE_RANGE, "V Pos.",  0, DEFAULT_POSITION,	DEFAULT_POSITION,                    DEFAULT_POSITION - 30,  DEFAULT_POSITION + 30,  1),
+	PD_MAKE_ATTR (PD_ATTR_ID_HSCALE,   PD_ATTR_TYPE_RANGE, "H_Scale",  0, HDMI_DEFAULT_UNDERSCAN,   HDMI_DEFAULT_UNDERSCAN,  10,  20,  1),
+	PD_MAKE_ATTR (PD_ATTR_ID_VSCALE,   PD_ATTR_TYPE_RANGE, "V_Scale",  0, HDMI_DEFAULT_UNDERSCAN,     HDMI_DEFAULT_UNDERSCAN,   10,  20,  1),
+	PD_MAKE_ATTR (PD_ATTR_ID_HSCALE_CRT,   PD_ATTR_TYPE_RANGE, "H_Scale",  0, CRT_DEFAULT_UNDERSCAN,   CRT_DEFAULT_UNDERSCAN,  10,  20,  1),
+	PD_MAKE_ATTR (PD_ATTR_ID_VSCALE_CRT,   PD_ATTR_TYPE_RANGE, "V_Scale",  0, CRT_DEFAULT_UNDERSCAN,   CRT_DEFAULT_UNDERSCAN,  10,  20,  1),
+	PD_MAKE_ATTR (PD_ATTR_ID_DITHER,   PD_ATTR_TYPE_RANGE, "Dither", PD_ATTR_FLAG_USER_INVISIBLE, 0,   0,  0,  3,  1),
+	
+	PD_MAKE_ATTR (PD_ATTR_ID_TEXT_FILTER,   PD_ATTR_TYPE_RANGE, "Text Tuning", PD_ATTR_FLAG_USER_INVISIBLE, 4,   DEFAULT_TEXT_ENHANCE,  0,  7,  1),
+	
+
+	PD_MAKE_ATTR (PD_ATTR_ID_DITHER_BYPASS, PD_ATTR_TYPE_BOOL, "Quality Enhance",  0, 0,                 0,                 0, 0, 0),
+	
+	PD_MAKE_ATTR (PD_ATTR_ID_PLL_REF_DLY, PD_ATTR_TYPE_BOOL, "Pll Reference Delay",PD_ATTR_FLAG_USER_INVISIBLE, 0,0,0, 0, 0),
+	PD_MAKE_ATTR (PD_ATTR_ID_PLL_REF_FBDLY,PD_ATTR_TYPE_BOOL, "Pll Reference FBDelay",PD_ATTR_FLAG_USER_INVISIBLE, 1,   1, 0, 0, 0),
+	
+	PD_MAKE_ATTR (PD_ATTR_ID_LOAD_FIRMWARE,PD_ATTR_TYPE_BOOL, "Load Firmware",PD_ATTR_FLAG_USER_INVISIBLE, 0, 1, 0, 0, 0),
+	PD_MAKE_ATTR (PD_ATTR_ID_REFRESH,PD_ATTR_TYPE_BOOL, "Refresh",0, 0,   0, 0, 0, 0),
+	PD_MAKE_ATTR (PD_ATTR_ID_DWNSCAL_BYPASS,PD_ATTR_TYPE_BOOL, "Remove_DS",PD_ATTR_FLAG_USER_INVISIBLE, 0, 1, 0, 0, 0),
+	
+};
+
+
+static ch7036_attr_list_entry_t g_list_entry_hdmi[] =
+{
+	{OUT_HDMI_640x480P_59,		"640x480p_59",PD_ATTR_FLAG_DYNAMIC}, 
+	{OUT_HDMI_640x480P_60,		"640x480p_60",PD_ATTR_FLAG_DYNAMIC}, 
+	{OUT_HDMI_720x480P_59,		"720x480p_59",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_HDMI_720x480P_60,		"720x480p_60",PD_ATTR_FLAG_DYNAMIC},
+
+	{OUT_HDMI_720x576P_50,     "720x576p_50",PD_ATTR_FLAG_DYNAMIC},
+
+	{OUT_HDMI_1280x720P_59,    "1280x720p_59",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_HDMI_1280x720P_60,    "1280x720p_60",PD_ATTR_FLAG_DYNAMIC}, 
+	{OUT_HDMI_1920x1080I_59,   "1920x1080i_59",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_HDMI_1920x1080I_60,   "1920x1080i_60",PD_ATTR_FLAG_DYNAMIC}, 
+	{OUT_HDMI_1920x1080P_59,   "1920x1080p_59",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_HDMI_1920x1080P_60,   "1920x1080p_60",PD_ATTR_FLAG_DYNAMIC}, 
+	
+	{OUT_HDMI_1280x720P_50,    "1280x720p_50",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_HDMI_1920x1080I_50,   "1920x1080i_50",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_HDMI_1920x1080P_50,   "1920x1080p_50",PD_ATTR_FLAG_DYNAMIC},
+	{0, NULL,0}
+};
+
+
+
+static ch7036_attr_list_entry_t g_list_entry_dvi[] =
+{
+
+	{OUT_DVI_640x480_60,	"640x480_60",PD_ATTR_FLAG_DYNAMIC}, 
+	{OUT_DVI_640x480_72,	"640x480_72",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_DVI_640x480_75,	"640x480_75",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_DVI_720x400_70,	"720x400_70",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_DVI_800x600_56,	"800x600_56",PD_ATTR_FLAG_DYNAMIC},
+
+	{OUT_DVI_800x600_60,	"800x600_60",PD_ATTR_FLAG_DYNAMIC}, 
+	{OUT_DVI_800x600_72,	"800x600_72",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_DVI_800x600_75,	"800x600_75",PD_ATTR_FLAG_DYNAMIC},
+
+	{OUT_DVI_1024x768_60,	"1024x768_60",PD_ATTR_FLAG_DYNAMIC}, 
+	{OUT_DVI_1024x768_70,	"1024x768_70",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_DVI_1024x768_75,	"1024x768_75",PD_ATTR_FLAG_DYNAMIC},
+
+	{OUT_DVI_1152x864_60,	"1152x864_60",PD_ATTR_FLAG_DYNAMIC}, 
+
+	{OUT_DVI_1280x720_60,   "1280x720_60",PD_ATTR_FLAG_DYNAMIC}, 
+	{OUT_DVI_1280x800_60,   "1280x800_60",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_DVI_1280x960_60,    "1280x960_60",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_DVI_1280x1024_60,   "1280x1024_60",PD_ATTR_FLAG_DYNAMIC}, 
+	{OUT_DVI_1280x1024_75,   "1280x1024_75",PD_ATTR_FLAG_DYNAMIC},
+
+	{OUT_DVI_1360x768_60,    "1360x768_60",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_DVI_1366x768_60,    "1366x768_60",PD_ATTR_FLAG_DYNAMIC},
+
+	{OUT_DVI_1400x1050_60,   "1400x1050_60",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_DVI_1400x1050_75,   "1400x1050_75",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_DVI_1440x900_60,    "1440x900_60",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_DVI_1440x1050_60,   "1440x1050_60",PD_ATTR_FLAG_DYNAMIC},
+
+	{OUT_DVI_1600x900_60,    "1600x900_60",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_DVI_1600x1200_60,   "1600x1200_60",PD_ATTR_FLAG_DYNAMIC}, 
+	{OUT_DVI_1680x1050_60,   "1680x1050_60",PD_ATTR_FLAG_DYNAMIC},
+
+	{OUT_DVI_1920x1080_60,   "1920x1080_60",PD_ATTR_FLAG_DYNAMIC}, 
+	{0, NULL,0}
+};
+
+
+
+static ch7036_attr_list_entry_t g_list_entry_crt[] =
+{
+	{OUT_CRT_640x400_85, "640x400_85",PD_ATTR_FLAG_DYNAMIC}, 
+
+	{OUT_CRT_640x480_60, "640x480_60",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_CRT_640x480_72, "640x480_72",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_CRT_640x480_75, "640x480_75",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_CRT_640x480_85, "640x480_85",PD_ATTR_FLAG_DYNAMIC},
+
+	{OUT_CRT_720x400_85, "720x400_85",PD_ATTR_FLAG_DYNAMIC},
+
+	{OUT_CRT_800x600_56, "800x600_56",PD_ATTR_FLAG_DYNAMIC},
+	
+	{OUT_CRT_800x600_60, "800x600_60",PD_ATTR_FLAG_DYNAMIC}, 
+	{OUT_CRT_800x600_72, "800x600_72",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_CRT_800x600_75, "800x600_75",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_CRT_800x600_85, "800x600_85",PD_ATTR_FLAG_DYNAMIC}, 
+	
+	{OUT_CRT_1024x768_60,"1024x768_60",PD_ATTR_FLAG_DYNAMIC}, 
+	{OUT_CRT_1024x768_70,"1024x768_70",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_CRT_1024x768_75,"1024x768_75",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_CRT_1024x768_85,"1024x768_85",PD_ATTR_FLAG_DYNAMIC},
+	
+
+	{OUT_CRT_1152x864_75,"1152x864_75",PD_ATTR_FLAG_DYNAMIC}, 
+
+	{OUT_CRT_1280x768_60,"1280x768_60",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_CRT_1280x768_75,"1280x768_75",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_CRT_1280x768_85,"1280x768_85",PD_ATTR_FLAG_DYNAMIC},
+
+	{OUT_CRT_1280x960_60,"1280x960_60",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_CRT_1280x960_85,"1280x960_85",PD_ATTR_FLAG_DYNAMIC},
+
+
+	{OUT_CRT_1280x1024_60,"1280x1024_60",PD_ATTR_FLAG_DYNAMIC}, 
+	{OUT_CRT_1280x1024_75,"1280x1024_75",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_CRT_1280x1024_85,"1280x1024_85",PD_ATTR_FLAG_DYNAMIC},
+
+	{OUT_CRT_1360x768_60,"1360x768_60",PD_ATTR_FLAG_DYNAMIC},
+
+	{OUT_CRT_1400x1050_60,"1400x1050_60",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_CRT_1400x1050_75,"1400x1050_75",PD_ATTR_FLAG_DYNAMIC},
+
+	{OUT_CRT_1440x900_60,"1440x900_60",PD_ATTR_FLAG_DYNAMIC},
+	{OUT_CRT_1440x1050_60,"1440x1050_60",PD_ATTR_FLAG_DYNAMIC},
+
+	{OUT_CRT_1600x900_60,"1600x900_60",PD_ATTR_FLAG_DYNAMIC},
+	
+	{OUT_CRT_1600x1200_60,"1600x1200_60",PD_ATTR_FLAG_DYNAMIC}, 
+	{OUT_CRT_1920x1080_60,"1920x1080_60",PD_ATTR_FLAG_DYNAMIC}, 
+	{0, NULL,0}
+};
+
+
+static ch7036_attr_list_entry_t g_list_entry_channel[] =
+{
+	{CHANNEL_AUTO_DETECT,"Auto Detect",PD_ATTR_FLAG_DYNAMIC},
+	{CHANNEL_LVDS_HDMI, "LVDS_HDMI",PD_ATTR_FLAG_DYNAMIC}, 
+	{CHANNEL_LVDS_DVI, "LVDS_DVI",PD_ATTR_FLAG_DYNAMIC},
+	{CHANNEL_LVDS_VGA,  "LVDS_VGA",PD_ATTR_FLAG_DYNAMIC},
+	{CHANNEL_HDMI, "HDMI",PD_ATTR_FLAG_DYNAMIC}, 
+	{CHANNEL_DVI, "DVI",PD_ATTR_FLAG_DYNAMIC},
+	{CHANNEL_VGA,  "VGA",PD_ATTR_FLAG_DYNAMIC},
+	{0, NULL,0}	
+};
+
+static ch7036_attr_list_header_t g_list_header[] =
+{
+	{7, PD_ATTR_ID_DISPLAY,"Display Channel", 1,1, 
+	g_list_entry_channel},
+
+	{14, PD_ATTR_ID_HDMI_OUT_MODE, "HDMI",7,7,
+	 g_list_entry_hdmi},
+
+	{27, PD_ATTR_ID_DVI_OUT_MODE,"DVI", 9,9,
+	 g_list_entry_dvi},
+
+	{32, PD_ATTR_ID_CRT_OUT_MODE, "VGA", 12,12,
+	 g_list_entry_crt},
+
+	{ 0 }
+};
+
+
+
+ch7036_status_t ch7036_init_attribute_table(ch7036_device_context_t *p_ctx, ch7036_attr_list_header_t* p_list_header)
+{
+	unsigned long ch7036_num_attrs, num_attrs;
+	unsigned char *p_table;
+	
+
+	
+	ch7036_num_attrs = ch7036_enumerate_attr_table(p_ctx, NULL, p_list_header);
+	PD_DEBUG("ch7036_init_attribute_table- ch7036 num_attr = [%lu]\n",ch7036_num_attrs);
+
+	
+	p_ctx->ch7036_num_attrs =  ch7036_num_attrs ;  
+
+
+	if(p_ctx->p_ch7036_attr_table) {
+		pd_free(p_ctx->p_ch7036_attr_table);
+		p_ctx->p_ch7036_attr_table = NULL;
+	}
+
+	
+	if(p_ctx->p_ch7036_attr_table == NULL) {
+	
+		p_ctx->p_ch7036_attr_table = pd_malloc((p_ctx->ch7036_num_attrs + 1) * sizeof(pd_attr_t)); 
+
+		if (p_ctx->p_ch7036_attr_table == NULL) {
+			PD_ERROR("ch7036: Error ! ch7036_init_attribute_table: pd_malloc() failed allocating ch7036_attr_table");
+		
+			return SS_MEM_ALLOC_ERR;
+		}
+
+		pd_memset(p_ctx->p_ch7036_attr_table, 0, (p_ctx->ch7036_num_attrs + 1) *
+			sizeof(pd_attr_t));
+
+	}
+
+
+	p_table = (unsigned char *)p_ctx->p_ch7036_attr_table;
+
+
+	if (p_ctx->ch7036_num_attrs  > 0) {
+
+		num_attrs = ch7036_enumerate_attr_table(p_ctx, (pd_attr_t *)p_table, p_list_header);
+
+
+		PD_DEBUG("ch7036_init_attribute_table: ch7036_enumerate_attr_table()- returned %lu entries, expected %lu\n",
+					  num_attrs, p_ctx->ch7036_num_attrs) ;
+
+	}
+
+	
+	return SS_SUCCESS;
+
+}
+
+
+
+unsigned long ch7036_enumerate_attr_table (ch7036_device_context_t *p_ctx,
+	pd_attr_t *p_attr, ch7036_attr_list_header_t* p_list_header)
+{
+
+	
+	unsigned long num_attrs, i, j, num_attrs_static;
+	ch7036_attr_list_entry_t *list_item;
+	int ret;
+	pd_attr_t *p_table;
+
+	list_item = NULL;
+	num_attrs = 0;
+	i = j = 0;
+
+	
+	PD_DEBUG("ch7036_enumerate_attr_table- enter\n");
+
+
+	
+	if ( p_list_header == NULL )
+			p_list_header = g_list_header; 
+		
+	
+	if (p_attr == NULL) {
+
+		if(p_ctx->p_ch7036_attr_table == NULL) { 
+			ret = PD_INTERNAL_LVDS_MODULE_GET_ATTRIBUTES(ch7036_lvds_get_attrs,(p_ctx->internal_lvds,&(p_ctx->lvds_num_attrs),&(p_ctx->p_lvds_attr_table))); 
+
+			if(ret != PD_SUCCESS)
+				PD_DEBUG("ch7036_enumerate_attr_table: lvds_get_attributes() return ERROR! check this routine\n");
+			else
+				PD_DEBUG("ch7036_enumerate_attr_table: lvds_get_attributes()- lvds num_attr = [%lu]\n",p_ctx->lvds_num_attrs);
+		}
+		
+				
+
+		while (p_list_header[i].num_entries) {
+
+
+			num_attrs += (p_list_header[i].num_entries + 1); 
+			++i;	 
+		}
+
+		num_attrs += ((sizeof(g_ch7036_attrs)/sizeof(pd_attr_t)) + p_ctx->lvds_num_attrs) ;
+
+		return num_attrs; 
+	}
+
+	
+	if(p_ctx->lvds_num_attrs > 0) {
+
+		pd_attr_t *p_lvds_des, *p_lvds_src ;
+
+		
+		p_lvds_src=  (pd_attr_t *)p_ctx->p_lvds_attr_table;
+		p_lvds_des = (pd_attr_t *)p_attr;
+
+		pd_memcpy(p_lvds_des, p_lvds_src, (p_ctx->lvds_num_attrs)*sizeof(pd_attr_t));
+		num_attrs += p_ctx->lvds_num_attrs;
+
+		for (i=0 ; i < p_ctx->lvds_num_attrs; i++, p_lvds_des++) {
+
+			PD_DEBUG("ch7036 : ch7036_enumerate_attr_table : \n"
+				  "adding lvds attr='%s', id=%lu, default=%lu, current=%lu, \n",
+				  p_lvds_des->name, p_lvds_des->id, p_lvds_des->default_value, p_lvds_des->current_value);
+		}
+
+	}
+
+	PD_DEBUG("ch7036 : ch7036_enumerate_attr_table adding lvds num attrs = %lu \n", num_attrs);
+
+	
+
+	i=0;
+
+
+	while (p_list_header[i].num_entries) {
+
+		pd_list_attr_t *p_hdr = (pd_list_attr_t *) &p_attr[num_attrs];
+
+	
+		p_hdr->type	= PD_ATTR_TYPE_LIST;
+		p_hdr->id = p_list_header[i].id;
+		p_hdr->num_entries = p_list_header[i].num_entries;
+		p_hdr->flags |= PD_ATTR_FLAG_DYNAMIC;
+
+		p_hdr->current_index = p_list_header[i].current_index;
+		pd_strcpy(p_hdr->name, p_list_header[i].p_name);
+
+		p_hdr->default_index = p_list_header[i].default_index;
+
+		PD_DEBUG("ch7036 : ch7036_enumerate_attr_table : \n"
+				  "adding attr - list header='%s', id=%lu, default=%lu, current=%lu, \n"
+				  "num_entries=%lu\n",
+				  p_hdr->name, p_hdr->id, p_hdr->default_index, p_hdr->current_index,
+				  p_hdr->num_entries);
+
+		++num_attrs;
+
+
+
+		list_item = p_list_header[i].attr_list;
+		for (j = 0; j < p_list_header[i].num_entries; ++j, ++num_attrs) {
+
+			pd_list_entry_attr_t *p_entry =
+				(pd_list_entry_attr_t *)&p_attr[num_attrs];
+
+			p_entry->id		= p_list_header[i].id;  
+			p_entry->type	= PD_ATTR_TYPE_LIST_ENTRY;
+			p_entry->value	= list_item[j].id;     
+			
+
+			p_entry->flags  = list_item[j].flags; 
+
+			
+			
+			
+			
+
+			
+
+			pd_strcpy(p_entry->name, list_item[j].p_name);
+
+			
+
+			PD_DEBUG("ch7036 : ch7036_enumerate_attr_table : list entry[%lu]=%s, id=[%lu], "
+					  "value=%lu, flags=0x%x \n",
+					  j, p_entry->name, p_entry->id,
+					  p_entry->value, (unsigned char)p_entry->flags);
+					  
+		}
+
+		++i;   
+	}
+
+	
+	p_table = (pd_attr_t *)&p_attr[num_attrs];
+	num_attrs_static = sizeof(g_ch7036_attrs)/sizeof(pd_attr_t);
+	pd_memcpy(p_table, g_ch7036_attrs,num_attrs_static*sizeof(pd_attr_t));
+
+	for (i=0 ; i < num_attrs_static; i++, p_table++) {
+
+		PD_DEBUG("ch7036 : ch7036_enumerate_attr_table : \n"
+				  "adding ch7036 static attr='%s', id=%lu, default=%lu, current=%lu, \n",
+				  p_table->name, p_table->id, p_table->default_value, p_table->current_value);
+
+	}
+
+	num_attrs += num_attrs_static;
+
+
+	return num_attrs;
+
+}
+
+void ch7036_set_dither(ch7036_device_context_t* p_ctx)
+{
+	uint8 reg=0x00;
+	DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
+	
+	I2CWrite(p_ch_ctx,0x03, 0x04);
+	reg = I2CRead(p_ch_ctx,0x57);
+    reg = reg & 0x3F;
+
+
+	switch(p_ctx->dither_select)
+	{
+		  case DITHER_18_TO_18: 
+			  reg &= 0x3F;
+			  break;
+		  case DITHER_18_TO_24: 
+			  reg = reg | 0x40;
+			  break;
+		  case DITHER_24_TO_18: 
+			  reg = reg | 0x80;		    
+			  break;
+		  case DITHER_24_TO_24: 
+			  reg = reg | 0xC0;
+			  break;
+		  default:
+			 break;
+    }
+	I2CWrite(p_ch_ctx,0x57, reg);
+
+	return;
+}
+
+
+
+void ch7036_set_audio_type(INPUT_INFO* pInput_Info, uint8 id)
+{
+	
+	pInput_Info->audio_type = id; 
+	
+	if(pInput_Info->audio_type == AUDIO_I2S) {
+		
+		
+		
+		
+		pInput_Info->i2s_pol = 0; 
+		pInput_Info->i2s_len = 0; 
+		pInput_Info->i2s_fmt = 0; 
+		
+	}
+}
+
+
+
+ch7036_status_t ch7036_set_output_channel(void* p_context, uint32 channel)
+{
+	ch7036_device_context_t * p_ctx= (ch7036_device_context_t *)p_context;
+	DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+	OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+	pd_attr_t *p_attr_hdmi, *p_attr_crt, *p_attr_dvi;
+	pd_attr_t *p_attr_hscale, *p_attr_vscale, *p_attr_hscale_crt, *p_attr_vscale_crt, *p_attr_hp, *p_attr_vp;
+	pd_attr_t* p_attr_dither;
+
+
+	
+	PD_DEBUG("ch7036_set_output_channel- channel [%x]\n", channel);
+	
+	pOutput_Info->channel = channel;
+
+
+
+	p_attr_dvi = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+				PD_ATTR_ID_DVI_OUT_MODE, PD_GET_ATTR_LIST);
+
+	p_attr_hdmi = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+				PD_ATTR_ID_HDMI_OUT_MODE, PD_GET_ATTR_LIST);
+	
+
+	p_attr_crt = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+			PD_ATTR_ID_CRT_OUT_MODE, PD_GET_ATTR_LIST);
+
+	
+	p_attr_hscale_crt = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+			PD_ATTR_ID_HSCALE_CRT, 0);
+	p_attr_vscale_crt = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+			PD_ATTR_ID_VSCALE_CRT, 0);
+	
+	p_attr_hscale = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+			PD_ATTR_ID_HSCALE, 0);
+	p_attr_vscale = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+			PD_ATTR_ID_VSCALE, 0);
+
+	p_attr_hp = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+				PD_ATTR_ID_HPOSITION, 0);
+	p_attr_vp = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+				PD_ATTR_ID_VPOSITION, 0);
+
+	p_attr_dither = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+				PD_ATTR_ID_DITHER_BYPASS, 0);
+			
+	
+
+	if(pOutput_Info->channel & CHANNEL_HDMI) {
+
+		if(pOutput_Info->hdmi_fmt.is_dvi_mode) {
+
+			if(p_attr_hdmi) 
+				p_attr_hdmi->flags |= PD_ATTR_FLAG_USER_INVISIBLE;  
+
+			p_attr_dvi->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE; 
+
+			
+			p_attr_dvi += p_attr_dvi->current_value; 
+			p_ctx->dvi_mode_index = ((pd_list_entry_attr_t *)p_attr_dvi)->value;
+
+			PD_DEBUG("ch7036_set_output_channel- dvi mode index [%hu]\n",p_ctx->dvi_mode_index);
+
+
+
+		}
+		else { 
+			
+			p_attr_hdmi->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE; 
+
+			if(p_attr_dvi) 
+				p_attr_dvi->flags |= PD_ATTR_FLAG_USER_INVISIBLE;  
+
+			
+			p_attr_hdmi += p_attr_hdmi->current_value; 
+			p_ctx->hdmi_mode_index = ((pd_list_entry_attr_t *)p_attr_hdmi)->value;
+
+			PD_DEBUG("ch7036_set_output_channel- hdmi mode index [%hu]\n",p_ctx->hdmi_mode_index);
+
+		}
+
+		if(p_attr_crt)
+			p_attr_crt->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+		
+		//hdmi/dvi- hide it from user
+		p_attr_hscale_crt->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+		p_attr_vscale_crt->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+		//h/v pos scale- hide it
+		p_attr_hp->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+		p_attr_vp->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+		
+		//show it
+		p_attr_hscale->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+		p_attr_vscale->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+
+
+		p_attr_dither->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+
+
+		PD_DEBUG("ch7036_set_output_channel-current hscale value [%d]\n",(uint8)p_attr_hscale->current_value);
+		PD_DEBUG("ch7036_set_output_channel-current vscale value [%d]\n",(uint8)p_attr_vscale->current_value);
+		
+		ch7036_set_scaling(pOutput_Info,PD_ATTR_ID_HSCALE,(uint8)p_attr_hscale->current_value);
+		ch7036_set_scaling(pOutput_Info,PD_ATTR_ID_VSCALE,(uint8)p_attr_vscale->current_value);
+
+
+	} else if (pOutput_Info->channel & CHANNEL_VGA) {
+		
+		p_attr_crt->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+		
+		if(p_attr_hdmi)
+			p_attr_hdmi->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+		if(p_attr_dvi)
+			p_attr_dvi->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+		p_attr_crt += p_attr_crt->current_value; 
+		p_ctx->crt_mode_index = ((pd_list_entry_attr_t *)p_attr_crt)->value;
+	
+		PD_DEBUG("ch7036_set_output_channel- crt mode index [%hu]\n",p_ctx->crt_mode_index);
+
+		
+		p_attr_hscale_crt->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+		p_attr_vscale_crt->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+		
+		p_attr_hp->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+		p_attr_vp->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+
+		p_attr_dither->flags &= ~PD_ATTR_FLAG_USER_INVISIBLE;
+
+
+		p_attr_hscale->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+		p_attr_vscale->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+		PD_DEBUG("ch7036_set_output_channel-current hscale_crt value [%d]\n",(uint8)p_attr_hscale_crt->current_value);
+		PD_DEBUG("ch7036_set_output_channel-current vscale_crt value [%d]\n",(uint8)p_attr_vscale_crt->current_value);
+
+		
+		ch7036_set_scaling(pOutput_Info,PD_ATTR_ID_HSCALE_CRT,(uint8)p_attr_hscale_crt->current_value);
+		ch7036_set_scaling(pOutput_Info,PD_ATTR_ID_VSCALE_CRT,(uint8)p_attr_vscale_crt->current_value);
+
+		
+	} else {
+
+		if(p_attr_crt)
+			p_attr_crt->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+		if(p_attr_hdmi)
+			p_attr_hdmi->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+		if(p_attr_dvi)
+			p_attr_dvi->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+		
+		p_attr_hscale->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+		p_attr_vscale->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+		p_attr_hscale_crt->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+		p_attr_vscale_crt->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+	
+		p_attr_hp->flags |= PD_ATTR_FLAG_USER_INVISIBLE;		
+		p_attr_vp->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+		p_attr_dither->flags |= PD_ATTR_FLAG_USER_INVISIBLE;
+
+
+	}
+	
+
+	return SS_SUCCESS;
+}
+unsigned long ch7036_get_output_channel(void* p_context)
+{
+	ch7036_device_context_t * p_ctx= (ch7036_device_context_t *)p_context;
+	pd_list_entry_attr_t *p_attr;
+	uint32 channel = 0;
+
+	PD_DEBUG("ch7036_get_output_channel- enter\n");
+
+	p_attr = (pd_list_entry_attr_t *)pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,
+			PD_ATTR_ID_DISPLAY, PD_GET_ATTR_LIST_ENTRY);
+
+	if(p_attr->value & CHANNEL_DVI)
+		channel = (p_attr->value & 0xF7) | CHANNEL_HDMI;
+
+	return channel;
+}
+
+ch7036_status_t ch7036_set_position(ch7036_device_context_t *p_ctx, uint8 attr_id, uint16 pos)
+{
+	DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+
+	uint8 reg;
+
+	PD_DEBUG("ch7036_set_position- enter\n");
+	I2CWrite(p_ch7xxx_context,0x03, 0x00);
+	reg = I2CRead(p_ch7xxx_context,0x39);
+	
+	if(attr_id == PD_ATTR_ID_HPOSITION) {
+		reg = reg & 0xF0; 
+		I2CWrite(p_ch7xxx_context,0x3A, (pos & 0x00FF));
+		reg = ((pos >> 8) & 0x0F) | reg;	
+		iic_write_ex(HP,pos);
+	} 
+	else { 
+		reg = reg & 0x0F;
+		I2CWrite(p_ch7xxx_context,0x3B, (pos & 0x00FF));
+		reg = (((pos >> 8) & 0x0F) << 4) | reg;	
+		iic_write_ex(VP,pos);
+	}
+
+	I2CWrite(p_ch7xxx_context,0x39, reg);
+	
+	return SS_SUCCESS;
+}
+
+
+void ch7036_set_hdmi_sync_polarity(OUTPUT_INFO* pOutput_Info)
+{
+	
+	if((pOutput_Info->channel & CHANNEL_HDMI)&&(pOutput_Info->channel & CHANNEL_VGA))
+	{
+		if (pOutput_Info->timing.ha > 720) {
+			pOutput_Info->hdmi_fmt.hs_pol = POL_HIGH;
+			pOutput_Info->hdmi_fmt.vs_pol = POL_HIGH;
+			if(pOutput_Info->timing.ha == 1440 )
+			{
+              pOutput_Info->hdmi_fmt.hs_pol = POL_LOW;
+			  pOutput_Info->hdmi_fmt.vs_pol = POL_LOW;
+			}
+		}
+		else if(pOutput_Info->timing.ha <= 720){
+			
+			pOutput_Info->hdmi_fmt.hs_pol = POL_LOW;
+			pOutput_Info->hdmi_fmt.vs_pol = POL_LOW;
+		}
+	}
+	
+	
+	if((pOutput_Info->channel & CHANNEL_HDMI) && ((pOutput_Info->channel & CHANNEL_VGA) == 0x00))
+	{	
+		pOutput_Info->hdmi_fmt.hs_pol = POL_LOW;
+		pOutput_Info->hdmi_fmt.vs_pol = POL_LOW;
+	}
+
+}
+
+void ch7036_set_quality_enhancement(ch7036_device_context_t *p_ctx, uint8 checked)
+{
+	DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+	PREFER_INFO* pPrefer_Info = p_ch7xxx_context->pPrefer_Info;
+	uint8 reg;
+
+	PD_DEBUG("ch7036_set_quality_enhancement- enter\n");
+	I2CWrite(p_ch7xxx_context,0x03, 0x00);	
+	reg = I2CRead(p_ch7xxx_context,0x19); 
+	
+	if(checked) 
+		reg = reg & 0xBF; 
+	else
+		reg = reg | 0x40; 
+	
+	I2CWrite(p_ch7xxx_context,0x19, reg);
+
+	
+	pPrefer_Info->dither_filter_enable = checked?DITHER_ENABLE:DITHER_BYPASS;
+
+	
+	iic_write_ex(DBP, checked?DITHER_ENABLE:DITHER_BYPASS);
+	
+}
+
+void ch7036_set_scaling (OUTPUT_INFO* pOutput_Info, unsigned long id, uint8 value)
+{
+	uint8* p_scale;
+
+	PD_DEBUG("ch7036_set_scaling- enter- value [%d]\n", value);
+		
+	if(id == PD_ATTR_ID_HSCALE || id == PD_ATTR_ID_HSCALE_CRT)
+		p_scale= &(pOutput_Info->ds_percent_h);
+	else 
+		p_scale= &(pOutput_Info->ds_percent_v);
+		
+	switch(value) {
+		case 20: *p_scale = 0; break; 
+		case 19: *p_scale = 1; break; 
+		case 18: *p_scale = 2; break;
+		case 17: *p_scale = 3; break;
+		case 16: *p_scale = 4; break;
+		case 15: *p_scale = 5; break;
+		case 14: *p_scale = 6; break;
+		case 13: *p_scale = 7; break;
+		case 12: *p_scale = 8; break;
+		case 11: *p_scale = 9; break;
+		case 10: *p_scale = 10; break;
+		
+		case 9: *p_scale = 11; break;
+		case 8: *p_scale = 12; break;
+		case 7: *p_scale = 13; break;
+		case 6: *p_scale = 14; break;
+		case 5: *p_scale = 15; break;
+		case 4: *p_scale = 16; break;
+		case 3: *p_scale = 17; break;
+		case 2: *p_scale = 18; break;
+		case 1: *p_scale = 19; break;
+		case 0: *p_scale = 20; break;
+		default: break;
+			
+	}
+
+	return;
+
+}
+
+void ch7036_set_rotate (OUTPUT_INFO* pOutput_Info)
+{
+	
+	
+	pOutput_Info->rotate = DEFAULT_ROTATE; 
+}
+
+void ch7036_set_hflip (OUTPUT_INFO* pOutput_Info)
+{
+	
+	
+	pOutput_Info->h_flip = DEFAULT_HFLIP; 
+}
+void ch7036_set_vflip (OUTPUT_INFO* pOutput_Info)
+{
+	
+	
+	pOutput_Info->v_flip = DEFAULT_VFLIP; 
+}
+
+void ch7036_set_text_enhancement (ch7036_device_context_t *p_ctx, uint8 val)
+{
+	
+	DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+	PREFER_INFO* pPrefer_Info = p_ch7xxx_context->pPrefer_Info;
+	
+
+	PD_DEBUG("ch7036_set_text_enhancement- enter\n");
+
+
+	I2CWrite(p_ch7xxx_context,0x03, 0x00);
+	I2CWrite(p_ch7xxx_context,0x2E, (I2CRead(p_ch7xxx_context,0x2E) & 0xF8) |  val);
+	
+	pPrefer_Info->text_enhancement = val; 
+	iic_write_ex(TXTEN, val);
+}
+
+
+void ch7036_set_pll_refdly(PREFER_INFO* pPrefer_Info)
+{
+	pPrefer_Info->pll_ref_dly = DEF_PLL_REF_DLY;
+}
+
+void ch7036_set_pll_fbdly(PREFER_INFO* pPrefer_Info)
+{
+	pPrefer_Info->pll_ref_fbdly = DEF_PLL_REF_FBDLY;
+}
+
+void ch7036_set_lvds_txdrv_ctrl(PREFER_INFO* pPrefer_Info)
+{
+	pPrefer_Info->lvds_txdrv_ctrl = DEF_LVDS_TXDRV_CTRL;
+}
+
+
+
+ch7036_status_t ch7036_alter_display_channel (ch7036_device_context_t *p_ctx) 
+{
+
+
+	ch7036_status_t status;
+
+
+	pd_list_entry_attr_t  *list_item;
+
+	ch7036_edid_blk_t* p_hedid = (ch7036_edid_blk_t *)p_ctx->hedid;
+	ch7036_edid_blk_t* p_cedid = (ch7036_edid_blk_t *)p_ctx->cedid;
+
+
+	list_item = (pd_list_entry_attr_t *)pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,PD_ATTR_ID_DISPLAY,
+					PD_GET_ATTR_LIST_ENTRY); 
+	
+	PD_DEBUG("ch7036_alter_display_channel=> enter- list_item->value [0x%lu]\n",list_item->value);
+	
+	switch (p_ctx->hpd & 0x22) {
+	
+		case 0x22: 
+		case 0x20:
+			PD_DEBUG("ch7036_alter_display_channel=> hdmi-dvi hpd status: attached... \n");
+			if(p_ctx->hpd & 0x41 ) { 
+
+				status = ch7036_read_edid(p_ctx, CHANNEL_LVDS_HDMI);
+
+		
+				if (status == SS_SUCCESS) {
+
+					if( p_ctx->man_sel_out==1 ) 
+						p_ctx->hpd &= 0x3F; //need parsing but dont do edid again
+					else													
+						p_ctx->hpd &= 0x7F; 
+					
+					
+					PD_DEBUG("ch7036_alter_display_channel=> hdmi-dvi, status changed,edid read is a success- proceed to alter attr table...\n");
+					
+				}
+				else { 
+
+					PD_DEBUG("ch7036_alter_display_channel=> hdmi-dvi, status changed,edid read failed- use default attr table- show all modes..\n");
+					
+
+				}
+
+					
+
+			}
+			else {
+
+				PD_DEBUG("ch7036_alter_display_channel=> hdmi/dvi, status unchanged,check if edid read needed...\n"); 
+				ch7036_redo_edid_if_needed(p_ctx, (void *)p_hedid, CHANNEL_LVDS_HDMI);
+			}
+
+	
+
+
+			if(list_item->value == CHANNEL_AUTO_DETECT) {
+				if(p_ctx->prev_outchannel != CHANNEL_LVDS_HDMI)	
+					ch7036_set_output_channel((void *)p_ctx, CHANNEL_LVDS_HDMI);
+			}
+			else { 
+
+	
+
+				
+				if(list_item->value & CHANNEL_DVI) 
+					//	map DVI to HDMI output channel;										
+					ch7036_set_output_channel((void *)p_ctx, (list_item->value & 0x01) | CHANNEL_HDMI);
+				
+				else 
+					
+					ch7036_set_output_channel((void *)p_ctx, (uint32)list_item->value );
+				
+
+			}
+	
+
+			break;
+
+		case 0x02: 
+			
+			PD_DEBUG("ch7036_alter_display_channel=> crt hpd status: attached... \n");
+		
+			if(p_ctx->hpd & 0x05) { 
+				
+				status = ch7036_read_edid(p_ctx, CHANNEL_LVDS_VGA);
+
+			
+				if (status == SS_SUCCESS) {
+
+					PD_DEBUG("ch7036_alter_display_channel=> crt only, status changed, edid is a success, proceed ..\n");
+					if( p_ctx->man_sel_out==1 ) 
+						p_ctx->hpd &= 0xF3; //need parsing,hpd manually updated to 'unchanged',dont do edid again
+					else
+						p_ctx->hpd &= 0xF7; 
+										
+				
+				}
+				else {
+
+					PD_DEBUG("ch7036_alter_display_channel=> crt only, status changed, edid failed- use default attr table- show all modes..\n");
+
+				} 
+							
+
+			} 
+			
+			else  {
+				PD_DEBUG("ch7036_alter_display_channel=> crt only, status unchange,check if edid read needed...\n"); 
+				ch7036_redo_edid_if_needed(p_ctx, (void *)p_cedid, CHANNEL_LVDS_VGA);
+			}
+				
+			if(list_item->value == CHANNEL_AUTO_DETECT)
+					ch7036_set_output_channel((void *)p_ctx, CHANNEL_LVDS_VGA);
+			else {
+
+				//set output channel, correct display choice if needed 				
+				ch7036_set_output_channel((void *)p_ctx, (uint32)list_item->value );
+			}
+			
+
+			break;
+
+		default: 
+
+			if(list_item->value == CHANNEL_AUTO_DETECT) {
+				if (!p_ctx->init_done) { 					
+					ch7036_set_output_channel((void *)p_ctx, CHANNEL_LVDS_VGA); 
+				}
+				else
+					ch7036_set_output_channel((void *)p_ctx, CHANNEL_LVDS);
+			}
+			else 		
+				ch7036_set_output_channel((void *)p_ctx, (uint32)list_item->value );
+			
+
+		break;
+
+
+	} 
+
+	PD_DEBUG("ch7036_alter_display_channel=> exit- list_item->value [0x%x]\n",list_item->value);
+	return SS_SUCCESS;
+
+}
+
+
+pd_list_entry_attr_t *ch7036_get_updated_display_ouput_entry(ch7036_device_context_t *p_ctx, uint32 channel)
+{
+		
+	pd_list_entry_attr_t  *list_item;
+
+	list_item = (pd_list_entry_attr_t *)pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,PD_ATTR_ID_DISPLAY,
+					PD_GET_ATTR_LIST_ENTRY); 
+
+	list_item->value = (list_item->value & 0x01) | channel; 
+
+	return list_item;			
+}
+
+
+void ch7036_redo_edid_if_needed(ch7036_device_context_t *p_ctx, void* p_edidblk, uint32 channel)
+{
+	ch7036_edid_blk_t* p_edid = (ch7036_edid_blk_t *)p_edidblk;
+	ch7036_status_t status = SS_UNSUCCESSFUL;;
+	
+	
+	
+	if (!p_ctx->init_done) { 
+					
+			PD_DEBUG("ch7036_alter_list: ch7036_check_if_edid_read_needed=> attached, status unchanged at init, read edid NOW...\n"); 
+			status = ch7036_read_edid(p_ctx, channel); 
+			
+	}
+	else {
+				
+		if(!p_edid->is_edid) { 
+			PD_DEBUG("ch7036_alter_list: ch7036_check_if_edid_read_needed=>attached, status unchanged, never read edid or edid failed, read it NOW..\n");
+			status= ch7036_read_edid(p_ctx, channel);
+
+
+		}
+		else 
+			PD_DEBUG("ch7036_alter_list: ch7036_check_if_edid_read_needed=> attached, status unchanged, edid read was done, edid read is NOT needed...\n");
+	}
+
+	if(status == SS_SUCCESS) { 
+
+		if(channel & CHANNEL_HDMI) 
+			if( p_ctx->man_sel_out==1 ) 
+				p_ctx->hpd &= 0x3F; 
+			else
+				p_ctx->hpd &= 0x7F;
+		
+		else 
+			if( p_ctx->man_sel_out==1 ) 
+				p_ctx->hpd &= 0xF3; 
+			else
+				p_ctx->hpd &= 0xF7;
+		
+	} 
+
+
+
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.h
new file mode 100644
index 0000000..4917394
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_attr.h
@@ -0,0 +1,85 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file  ch7036_attr.h
+* @version 1.2.5
+*-----------------------------------------------------------------------------
+*/
+
+
+
+//#include <linux/kernel.h>
+
+#ifndef _CH7036_ATTR_H_
+#define _CH7036_ATTR_H_
+
+typedef struct {
+	unsigned long id;
+	char *p_name;
+	unsigned long flags; 
+
+} ch7036_attr_list_entry_t;
+
+typedef struct {
+	unsigned char num_entries;
+	unsigned long id;
+	char *p_name;
+	unsigned long default_index; 
+	unsigned long current_index;
+	ch7036_attr_list_entry_t *attr_list;
+	
+} ch7036_attr_list_header_t;
+
+
+unsigned long ch7036_enumerate_attr_table(ch7036_device_context_t *p_ctx,pd_attr_t *p_attr,ch7036_attr_list_header_t* p_list_header);
+ch7036_status_t ch7036_init_attribute_table(ch7036_device_context_t *p_ctx,ch7036_attr_list_header_t* p_list_header);
+
+
+void ch7036_set_hdmi_sync_polarity(OUTPUT_INFO* pOutput_Info);
+void ch7036_set_audio_type(INPUT_INFO* pInput_Info, uint8 id);
+void ch7036_set_scaling (OUTPUT_INFO* pOutput_Info, unsigned long id, uint8 value );
+ch7036_status_t ch7036_set_position(ch7036_device_context_t *p_ctx, uint8 attr_id, uint16 pos);
+
+
+void ch7036_set_rotate (OUTPUT_INFO* pOutput_Info);
+void ch7036_set_hflip (OUTPUT_INFO* pOutput_Info);
+void ch7036_set_vflip (OUTPUT_INFO* pOutput_Info);
+
+ch7036_status_t ch7036_set_output_channel(void* p_context, uint32 channel);
+unsigned long ch7036_get_output_channel(void* p_context);
+ch7036_status_t ch7036_alter_display_channel (ch7036_device_context_t *p_ctx);
+
+pd_list_entry_attr_t * ch7036_get_updated_display_ouput_entry(ch7036_device_context_t *p_ctx, uint32 channel);
+
+void ch7036_set_text_enhancement (ch7036_device_context_t *p_ctx, uint8 val);
+void ch7036_set_quality_enhancement(ch7036_device_context_t *p_ctx, uint8 val);
+
+void ch7036_set_pll_refdly(PREFER_INFO* pPrefer_Info);
+void ch7036_set_pll_fbdly(PREFER_INFO* pPrefer_Info);
+void ch7036_set_lvds_txdrv_ctrl(PREFER_INFO* pPrefer_Info);
+
+void ch7036_set_dither(ch7036_device_context_t* p_ctx);
+
+void ch7036_redo_edid_if_needed(ch7036_device_context_t *p_ctx, void* p_edidblk, uint32 channel);
+
+
+#endif 
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_def_regmap.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_def_regmap.h
new file mode 100755
index 0000000..d2e82fc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_def_regmap.h
@@ -0,0 +1,700 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file  ch7036_def_regmap.h
+* @version 1.2.2
+*-----------------------------------------------------------------------------
+*/
+
+#ifndef _CH7036_DEF_REGMAP_H
+#define _CH7036_DEF_REGMAP_H
+
+#include "ch7036_typedef.h"
+
+
+
+#define REG_PAGE_NUM		5
+#define REG_NUM_PER_PAGE	0x80
+
+static uint8 g_DefRegMap[5][0x80] = {
+	
+	{
+	0x56, 
+	0xF0, 
+	0xF3, 
+	0x00, 
+	0x36, 
+	0x58, 
+	0xAC, 
+	0xDD, 
+	0x0F, 
+	0x1F, 
+	0xB4, 
+	0x1A, 
+	0x80, 
+	0x20, 
+	0x00, 
+	0x10, 
+	0x60, 
+	0x11, 
+	0xE0, 
+	0x0D, 
+	0x00, 
+	0x0A, 
+	0x02, 
+	0x00, 
+	0x00, 
+	0xF8, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x1A, 
+	0x80, 
+	0x20, 
+	0x00, 
+	0x10, 
+	0x60, 
+	0x11, 
+	0xE0, 
+	0x0D, 
+	0x00, 
+	0x0A, 
+	0x02, 
+	0x08, 
+	0x00, 
+	0x00, 
+	0x3C, 
+	0x00, 
+	0x01, 
+	0x01, 
+	0xC0, 
+	0x01, 
+	0x01, 
+	0x80, 
+	0x40, 
+	0x40, 
+	0x47, 
+	0x88, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x86, 
+	0x00, 
+	0x11, 
+	0x0E, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x40, 
+	0x40, 
+	0x80, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x1F, 
+	0xFF, 
+	0x00, 
+	0x80, 
+	0x10, 
+	0x60, 
+	0x00, 
+	0x0A, 
+	0x02, 
+	0x08, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x40, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x01, 
+	0x2D, 
+	0x90, 
+	0x20, 
+	0x22, 
+	0x44, 
+	0x24, 
+	0x40, 
+	0x00, 
+	0x10, 
+	0x00, 
+	0xA0, 
+	0x4B, 
+	0x18, 
+	0x01, 
+	0x00, 
+	0x00, 
+	0x20, 
+	0x80, 
+	0x18, 
+	0x00, 
+	0x00, 
+	0x01, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0xFF, 
+	0x0F, 
+	0x00, 
+	},
+
+	
+	{
+	0x56, 
+	0xF0, 
+	0xF3, 
+	0x01, 
+	0x36, 
+	0x58, 
+	0xAC, 
+	0x20, 
+	0x00, 
+	0x4B, 
+	0x00, 
+	0x6D, 
+	0x6A, 
+	0x51, 
+	0x93, 
+	0x1C, 
+	0x00, 
+	0x08, 
+	0xC5, 
+	0xA8, 
+	0x91, 
+	0x68, 
+	0x29, 
+	0x0E, 
+	0xC8, 
+	0x42, 
+	0x6C, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x10, 
+	0x07, 
+	0xFF, 
+	0xB6, 
+	0x10, 
+	0x00, 
+	0x00, 
+	0x15, 
+	0x18, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x0B, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x08, 
+	0x60, 
+	0x14, 
+	0x20, 
+	0x00, 
+	0x00, 
+	0x20, 
+	0x00, 
+	0x49, 
+	0x10, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0x00, 
+	0x08, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0xA0, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x7A, 
+	0x5E, 
+	0x6E, 
+	0x1F, 
+	0x1F, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x20, 
+	0x40, 
+	0x40, 
+	0x40, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0x50, 
+	0x00, 
+	0x00, 
+	0x09, 
+	0x00, 
+	0x00, 
+	0x70, 
+	0x00, 
+	0x50, 
+	0x00, 
+	0x98, 
+	0x00, 
+	0x98, 
+	0xFF, 
+	0x00, 
+	0x00, 
+	0x00, 
+	},
+
+	
+	{
+	0x56, 
+	0xF0, 
+	0xF3, 
+	0xFF, 
+	0x36, 
+	0x58, 
+	0xAC, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	},
+
+	
+	{
+	0x56, 
+	0xF0, 
+	0xF3, 
+	0x03, 
+	0x36, 
+	0x58, 
+	0xAC, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0xFF, 
+	0x00, 
+	0x03, 
+	0x19, 
+	0x40, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x11, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0x09, 
+	0x1D, 
+	0x0F, 
+	0x00, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0x00, 
+	0x00, 
+	0xFF, 
+	0xF8, 
+	0xFF, 
+	0x00, 
+	0x02, 
+	0xFF, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	},
+
+	
+	{
+	0x56, 
+	0xF0, 
+	0xF3, 
+	0x04, 
+	0x36, 
+	0x58, 
+	0xAC, 
+	0xFF, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0xC0, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0x00, 
+	0x00, 
+	0x4F, 
+	0x07, 
+	0x4F, 
+	0x07, 
+	0x3B, 
+	0x07, 
+	0x3B, 
+	0x07, 
+	0x50, 
+	0x00, 
+	0x50, 
+	0x00, 
+	0x10, 
+	0x00, 
+	0x00, 
+	0x10, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0x00, 
+	0x03, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x24, 
+	0x00, 
+	0x40, 
+	0xFF, 
+	0xFF, 
+	0x7F, 
+	0x56, 
+	0x80, 
+	0x2F, 
+	0x00, 
+	0x84, 
+	0x60, 
+	0xAF, 
+	0x00, 
+	0x00, 
+	0x80, 
+	0x94, 
+	0x00, 
+	0x80, 
+	0x00, 
+	0x05, 
+	0x38, 
+	0x01, 
+	0x83, 
+	0x11, 
+	0x01, 
+	0x80, 
+	0x90, 
+	0x00, 
+	0x40, 
+	0x40, 
+	0xE4, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x00, 
+	0x89, 
+	0x10, 
+	0xAC, 
+	0x00, 
+	0xE0, 
+	0x80, 
+	0x80, 
+	0x19, 
+	0x7D, 
+	0x00, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0xFF, 
+	0x00, 
+	0x0C, 
+	},
+};
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.c
new file mode 100755
index 0000000..23490d7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.c
@@ -0,0 +1,468 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file  ch7036_fw.c
+* @version 1.2.5
+*-----------------------------------------------------------------------------
+*/
+
+
+
+#include "ch7036_intf.h"
+
+#include "edid7036.car"
+
+
+#define EDID_RETRY_MAX_TIMES 5
+#define HPD_LOOP_MAX 10
+
+
+#define SLEEP_TIME 200 
+
+
+#define lhfm_size  sizeof(lhfm_array)
+
+#define LHFM_TIMEOUT	10  
+
+static unsigned char edid_header[8]={0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00};
+
+static unsigned char es_map[16] = {   
+	0x26,0x27,0x42,0x43,0x44,0x45,0x46,0x47,
+	0x6A,0x51,0x52,0x53,0x57,0x58,0x59,0x5A	
+};
+
+
+
+
+
+established_timings_t et_I[8] = {
+	{0,"800x600_60", {OUT_DVI_800x600_60,OUT_HDMI_END, OUT_CRT_800x600_60} },
+	{0,"800x600_56", {OUT_DVI_800x600_56,OUT_HDMI_END, OUT_CRT_800x600_56} },
+	{0,"640x480_75", {OUT_DVI_640x480_75, OUT_HDMI_END, OUT_CRT_640x480_75} },
+	{0,"640x480_72", {OUT_DVI_640x480_72, OUT_HDMI_END, OUT_CRT_640x480_72} },
+	{0,"640x480_67", {OUT_DVI_END, OUT_HDMI_END, OUT_CRT_END } },
+	{0,"640x480_60", {OUT_DVI_640x480_60, OUT_HDMI_640x480P_60, OUT_CRT_640x480_60} },
+	{0,"720x400_88", {OUT_DVI_END, OUT_HDMI_END, OUT_CRT_END } },
+	{0,"720x400_70", {OUT_DVI_720x400_70, OUT_HDMI_END, OUT_CRT_END} },
+};
+
+established_timings_t et_II[8] ={
+	{0, "1280x1024_75", {OUT_DVI_1280x1024_75, OUT_HDMI_END, OUT_CRT_1280x1024_75} },
+	{0, "1024x768_75", {OUT_DVI_1024x768_75, OUT_HDMI_END, OUT_CRT_1024x768_75} },
+	{0, "1024x768_70", {OUT_DVI_1024x768_70, OUT_HDMI_END, OUT_CRT_1024x768_70} },
+	{0, "1024x768_60", {OUT_DVI_1024x768_60, OUT_HDMI_END, OUT_CRT_1024x768_60} },
+	{0, "1024x768_87", {OUT_DVI_END, OUT_HDMI_END, OUT_CRT_END} },
+	{0, "832x624_75", {OUT_DVI_END, OUT_HDMI_END, OUT_CRT_END} },
+	{0, "800x600_75", {OUT_DVI_800x600_75, OUT_HDMI_END, OUT_CRT_800x600_75} },
+	{0, "800x600_72", {OUT_DVI_800x600_72, OUT_HDMI_END, OUT_CRT_800x600_72} }
+};
+
+established_timings_t et_man = {
+	0, "1152x870_75", {OUT_DVI_END, OUT_HDMI_END, OUT_CRT_END} 
+};
+
+
+int LHFM_get_version(DEV_CONTEXT* p_ch7xxx_context,struct _FW7036_CFG* cfg)
+{
+
+	unsigned char reg;
+	unsigned wj;
+
+		 I2CWrite(p_ch7xxx_context,0x03, 0x00); 
+		 reg = I2CRead(p_ch7xxx_context,0x4F);
+		 
+
+		 if (0==(LHFM_REQUEST & reg)) { 
+			 I2CWrite(p_ch7xxx_context,0x4F, (LHFM_REQUEST+LHFM_GET_VERSION)); 
+			 wj = 0;
+			 while (wj++< LHFM_TIMEOUT) {
+			 
+			 				
+				 I2CWrite(p_ch7xxx_context,0x03, 0x00); 
+				 pd_usleep(SLEEP_TIME );
+				 PD_DEBUG("LHFM_get_version [%x]\r\n", wj);
+
+				 reg = I2CRead(p_ch7xxx_context,0x4F);
+				 if(reg == LHFM_GET_VERSION) {
+					 reg = I2CRead(p_ch7xxx_context,0x50);			
+					 if (!(LHFM_RET_ERROR & reg)) {
+						    I2CWrite(p_ch7xxx_context,0x03, 0x01); 
+						    cfg->size = I2CRead(p_ch7xxx_context,es_map[0]);	 
+							cfg->ver_major = I2CRead(p_ch7xxx_context,es_map[1]);
+							cfg->ver_minor = I2CRead(p_ch7xxx_context,es_map[2]);
+							cfg->did = I2CRead(p_ch7xxx_context,es_map[3]);
+							cfg->rid = I2CRead(p_ch7xxx_context,es_map[4]);
+							cfg->capbility = I2CRead(p_ch7xxx_context,es_map[5]);
+							cfg->reserved = I2CRead(p_ch7xxx_context,es_map[6]);
+						    I2CWrite(p_ch7xxx_context,0x03, 0x00); 
+							return 0;
+					 } else return -2;
+
+				 } 
+				 				 				
+			 }  
+
+		 } 
+
+	return -1; 
+}
+
+
+void LHFM_enable_crt_hpd(DEV_CONTEXT* p_ch7xxx_context)
+{
+	uint8 reg;
+	
+	PD_DEBUG("ch7036: LHFM_enable_crt_hpd-enter\n");
+
+	I2CWrite(p_ch7xxx_context,0x03, 0x04); 
+	reg = I2CRead(p_ch7xxx_context,0x57);
+	I2CWrite(p_ch7xxx_context,0x57, reg | 0x02); 
+	   
+	pd_usleep(SLEEP_TIME);
+
+	I2CWrite(p_ch7xxx_context,0x03, 0x00); 
+	I2CWrite(p_ch7xxx_context,0x08, I2CRead(p_ch7xxx_context,0x08) & 0xF1);
+	
+	pd_usleep(SLEEP_TIME);
+}
+
+
+ch7036_status_t LHFM_get_crt_hpd(DEV_CONTEXT* p_ch7xxx_context)
+{
+
+	unsigned char reg, count =0;
+	ch7036_status_t status = SS_CRT_HPD_NOTCONNECTED;
+
+	do {
+		
+		I2CWrite(p_ch7xxx_context,0x03, 0x00); 
+		reg = I2CRead(p_ch7xxx_context,0x74); 
+		I2CWrite(p_ch7xxx_context,0x74, reg & 0xFD); 
+		pd_usleep(SLEEP_TIME);
+
+		I2CWrite(p_ch7xxx_context,0x03, 0x00); 
+		reg = I2CRead(p_ch7xxx_context,0x74);
+		I2CWrite(p_ch7xxx_context,0x74, reg | 0x02); 		
+		pd_usleep(SLEEP_TIME);
+
+		I2CWrite(p_ch7xxx_context,0x03, 0x01); 
+		reg = I2CRead(p_ch7xxx_context,0x7C); 		
+		
+		if( (reg & 0xF0) == 0x50  || (reg & 0xF4) == 0x14 || (reg & 0xF4) == 0x44) 
+			status= SS_SUCCESS;
+					      	   	    
+	} while ( (status == SS_CRT_HPD_NOTCONNECTED) && ( (++count) < HPD_LOOP_MAX ) );
+
+          
+	I2CWrite(p_ch7xxx_context,0x03, 0x00); 	        
+	reg = I2CRead(p_ch7xxx_context,0x74);	        
+	I2CWrite(p_ch7xxx_context,0x74, reg & 0xFD);	 
+
+	I2CWrite(p_ch7xxx_context,0x08, I2CRead(p_ch7xxx_context,0x08) | 0x0E);
+		
+	return status;
+
+}
+
+
+ch7036_status_t LHFM_get_hdmi_modeinfo(DEV_CONTEXT* p_ch7xxx_context,unsigned char *minfo)
+{
+	unsigned char reg;
+	unsigned wj;
+	unsigned i;
+
+		 I2CWrite(p_ch7xxx_context,0x03, 0x00); 
+		 reg = I2CRead(p_ch7xxx_context,0x4F);
+		 
+		 if (0==(LHFM_REQUEST & reg)) {
+			 I2CWrite(p_ch7xxx_context,0x4F, (LHFM_REQUEST+ LHFM_GET_MODEINFO)); 
+			 wj = 0;
+			 while (wj++< LHFM_TIMEOUT) {
+				 I2CWrite(p_ch7xxx_context,0x03, 0x00); 
+				 pd_usleep(SLEEP_TIME);
+
+				 reg = I2CRead(p_ch7xxx_context,0x4F);
+				 if(reg == LHFM_GET_MODEINFO) {					 
+					 reg = I2CRead(p_ch7xxx_context,0x50);			
+					 if (!(LHFM_RET_ERROR & reg)) {
+						 if (minfo) {
+						    I2CWrite(p_ch7xxx_context,0x03, 0x01); 
+							for (i=0; i<15; i++) minfo[i] = I2CRead(p_ch7xxx_context,es_map[i]);	 
+						}
+						return SS_SUCCESS;
+					 } else return SS_FIRMWARE_ERR;
+
+				 } 
+				 			
+			 } 
+
+		 } 
+
+	return SS_FIRMWARE_TIMEOUT;
+
+}
+
+
+ch7036_status_t LHFM_get_edid(DEV_CONTEXT* p_ch7xxx_context,unsigned char* edid, unsigned char* ebn, unsigned char flag)
+{
+
+	unsigned i,j, ie;
+	unsigned k1, k2;
+	unsigned char reg;
+	unsigned wj;
+
+	ch7036_status_t status;
+
+
+
+	status = SS_SUCCESS;
+	*ebn = 0;    
+
+	pd_memset(edid, 0, EDID_SIZE); 
+
+	I2CWrite(p_ch7xxx_context,0x03, 0x00); 
+	reg = I2CRead(p_ch7xxx_context,0x4F);
+
+	if( (reg & LHFM_REQUEST) != 0 )
+		return SS_FIRMWARE_ERR; //mcu is busy
+	else { //mcu is ready to serve host request
+       
+		for(i=0,j=0; i < 8; i++,j+=16) {
+
+		    I2CWrite(p_ch7xxx_context,0x03, 0x00); 
+			I2CWrite(p_ch7xxx_context,0x50, i | flag); 
+			I2CWrite(p_ch7xxx_context,0x4F, (LHFM_REQUEST+LHFM_GET_EDID)); 
+			wj = 0;
+
+			status = SS_FIRMWARE_TIMEOUT;
+			PD_DEBUG("ch7036: LHFM_get_edid- block [%d] - getting [%d]- 16 bytes - wj=[0x%x]\n",*ebn,i+1,wj);
+			while (wj++< (2*LHFM_TIMEOUT) ) { 
+				 I2CWrite(p_ch7xxx_context,0x03, 0x00); 
+				 pd_usleep(SLEEP_TIME);
+				 
+				 reg = I2CRead(p_ch7xxx_context,0x4F);
+				 
+				 if(reg == LHFM_GET_EDID) { 
+					 
+					 reg = I2CRead(p_ch7xxx_context,0x50);	
+					 
+					 if (!(LHFM_RET_ERROR & reg)) { 
+							I2CWrite(p_ch7xxx_context,0x03, 0x01); 
+							for (ie=0; ie<16; ie++) edid[j+ie] = I2CRead(p_ch7xxx_context,es_map[ie] );								
+							break; 
+					 }
+					 else 						
+							return SS_FIRMWARE_ERR; 															 
+
+				 } 
+				 
+				 				 
+			} //while block
+			
+			status = SS_SUCCESS; 
+
+		} //for
+
+		for(i=0;i<8;i++)
+			if (edid_header[i] != edid[i]) {
+				return SS_FIRMWARE_ERR;
+			}
+		
+		(*ebn)++;
+		
+		if(flag & 0x80 && (edid[0x7E] > 0) ) { 
+			PD_DEBUG("ch7036: LHFM_get_edid- incorrect # of VGA EDID blocks read [%x]\n",edid[0x7E]); 
+			return SS_FIRMWARE_ERR;
+		}
+		
+		k2 = edid[0x7E];
+
+		k2 = (k2 > 3)? 3 : k2;  
+		
+		if (k2>0) { //case: there are more than 1 blocks
+			for (k1=1; k1<=k2; k1++) {
+
+				for(i=k1*8; i < 8+k1*8; i++,j+=16){
+					I2CWrite(p_ch7xxx_context,0x03, 0x00); 
+					I2CWrite(p_ch7xxx_context,0x50, i + flag);  
+					I2CWrite(p_ch7xxx_context,0x4F, (LHFM_REQUEST+LHFM_GET_EDID)); 
+					wj = 0;
+				
+					status = SS_FIRMWARE_TIMEOUT;
+					PD_DEBUG("ch7036: LHFM_get_edid- block [%d] - getting [%d]- 16 bytes - wj=[0x%x]\n",k1,i+1,wj);
+					while (wj++< (2*LHFM_TIMEOUT)) {
+						I2CWrite(p_ch7xxx_context,0x03, 0x00); 
+						pd_usleep(SLEEP_TIME);
+					 
+						reg = I2CRead(p_ch7xxx_context,0x4F);
+					 
+						if(reg == LHFM_GET_EDID) {						 
+							reg = I2CRead(p_ch7xxx_context,0x50);			
+							if (!(LHFM_RET_ERROR & reg)) {
+								I2CWrite(p_ch7xxx_context,0x03, 0x01); 
+								for (ie=0; ie<16; ie++) edid[j+ie] = I2CRead(p_ch7xxx_context,es_map[ie] );			
+								break;
+							}
+							else 
+								return SS_FIRMWARE_ERR;
+	
+
+						} 
+					 
+					} //while
+
+					status = SS_SUCCESS;
+
+				}//nested for 
+
+				(*ebn)++;
+
+			} //outermost for
+
+
+		} //if- case: there are more than 1 blocks
+
+	} //else - case:  mcu is ready to serve host request
+	
+	return status; 
+				
+}
+
+
+int LHFM_load_firmware(DEV_CONTEXT* p_ch7xxx_context)
+{
+
+
+	unsigned fs1;
+	unsigned char ch;
+
+	PD_DEBUG("ch7036: LHFM_load_firmware- firmware size [0x%.8X]\n",lhfm_size);
+	
+	I2CWrite(p_ch7xxx_context,0x03, 0x04);
+	ch = 0x29 | I2CRead(p_ch7xxx_context,0x52);
+	I2CWrite(p_ch7xxx_context,0x52, ch & 0xFB); 
+   
+
+	I2CWrite(p_ch7xxx_context,0x5B, 0x9E); 
+	I2CWrite(p_ch7xxx_context,0x5B, 0xB3);
+
+	I2CWrite(p_ch7xxx_context,0x03, 0x04);
+	I2CWrite(p_ch7xxx_context,0x03, 0x07);
+
+	for (fs1=0; fs1<lhfm_size; fs1++) 
+		I2CWrite(p_ch7xxx_context, 0x07, lhfm_array[fs1]);  
+
+
+
+	I2CWrite(p_ch7xxx_context, 0x03, 0x03); 
+	ch = I2CRead(p_ch7xxx_context,0x74); 
+	if (ch & 0x1) { 
+		
+		return -1;
+	}
+	else {
+		
+		I2CWrite( p_ch7xxx_context,0x03, 0x04); 
+		ch = I2CRead(p_ch7xxx_context,0x52);
+		I2CWrite(p_ch7xxx_context, 0x52, ch | 0x24);  
+	}
+
+	I2CWrite(p_ch7xxx_context, 0x03, 0x00);
+
+	return 0;
+}
+#if 0
+void ch7036_dump( char *s, int size, unsigned char *regdata)
+{
+	char temp[18];
+    int ch;
+
+    int i,j, size1;
+    
+    temp[16] = '?'; 
+    temp[17] = '\n';
+
+	PD_DEBUG("\n");
+    PD_DEBUG("+--------------------------------------------------------------------+\n");
+    PD_DEBUG("|%s |\n",s);
+    PD_DEBUG("+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-----------------+\n");
+    PD_DEBUG("|  | 0| 1| 2| 3| 4| 5| 6| 7| 8| 9| A| B| C| D| E| F|                 |\n");
+    PD_DEBUG("++++--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-----------------+\n");
+    
+    size1 = size % 16; 
+    size = size/16; 
+
+    for (i=0; i<size; i++) {
+
+       
+       PD_DEBUG("|%02x>", 0xFF & i*16);
+
+       
+	   for (j=0; j<16; j++) {
+           ch = regdata[i*16+j];
+           PD_DEBUG("%02X|", ch);
+
+#if 0
+		   
+          
+		   if( (ch >= 0x30 && ch <= 0x39) || (ch >= 0x61 && ch <= 0x7A) || (ch >= 0x41 && ch <= 0x5C) ) 
+				temp[j]='.';
+		   else
+			   temp[j]=(char)ch; 
+#endif
+		   
+        }
+             
+	   PD_DEBUG("\n");
+	}
+
+	if (size1) {
+	
+        PD_DEBUG( "|%02x>", 0xFF & size*16);
+
+		for (j=0; j<size1; j++) {
+           ch = regdata[size*16+j];
+           PD_DEBUG("%02X|", ch);
+#if 0
+         
+			if( (ch >= 0x30 && ch <= 0x39) || (ch >= 0x61 && ch <= 0x7A) || (ch >= 0x41 && ch <= 0x5C) ) 
+				temp[j]='.';
+		   else
+			   temp[j]=(char)ch; 
+#endif
+
+        }
+		for (j=size1; j<16; j++) {
+     
+           PD_DEBUG("   ");
+      
+        }
+    
+	}
+   
+	PD_DEBUG("\n");
+
+    return;
+}
+#endif
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.h
new file mode 100755
index 0000000..cc4a321
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_fw.h
@@ -0,0 +1,213 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file  ch7036_fw.h
+* @version 1.2.2
+*-----------------------------------------------------------------------------
+*/
+
+
+#ifndef H_FW_OPER_H
+#define H_FW_OPER_H
+
+#include "ch7036_typedef.h"
+
+
+//#include <linux/kernel.h>
+
+#define	CFG_CAP_EDID	0x01
+#define CFG_CAP_HDCP	0x02
+
+typedef unsigned char ch7036_attr_table_index_t;
+
+
+typedef struct _FW7036_CFG {
+    unsigned char size;	 
+	unsigned char ver_major;
+	unsigned char ver_minor;
+	unsigned char did;
+	unsigned char rid;
+	unsigned char capbility;
+	unsigned char reserved;
+} FW7036_CFG;
+
+
+#define LHFM_GET_VERSION		0x1F
+#define LHFM_GET_HPD			0x06
+#define LHFM_GET_EDID			0x01
+#define LHFM_GET_MODEINFO		0x03
+#define LHFM_GET_VGA_MODEINFO	0x33
+#define LHFM_HDMI_ONOFF		0x04 
+#define LHFM_REQUEST		0x40
+#define LHFM_RET_ERROR		0x80
+
+int LHFM_get_version(DEV_CONTEXT* p_ch7xxx_context,struct _FW7036_CFG* cfg);
+
+void LHFM_enable_crt_hpd(DEV_CONTEXT* p_ch7xxx_context);
+ch7036_status_t LHFM_get_crt_hpd(DEV_CONTEXT* p_ch7xxx_context);
+int LHFM_hdmi_onoff(int turnon);
+ch7036_status_t LHFM_get_hdmi_modeinfo(DEV_CONTEXT* p_ch7xxx_context,unsigned char *minfo);
+ch7036_status_t LHFM_get_edid(DEV_CONTEXT* p_ch7xxx_context,unsigned char*edid, unsigned char* ebn, unsigned char flag);
+int LHFM_load_firmware(DEV_CONTEXT* pDevContext);
+void ch7036_dump( char *s, int size, unsigned char *regdata);
+
+#define GET_VER					0x01
+#define GET_HPD					0x02
+#define GET_EDID				0x04
+#define GET_HDMI_DISPLAY_MODES	0x08
+
+#define GET_CRT_HPD				0x10
+#define GET_CRT_EDID			0x20
+
+#define CH7036_HDMI_DDC			0
+#define CH7036_VGA_DDC			0x80
+
+#define MAX_EDID_BLOCKS			2
+
+#define MAX_I2C_BLOCK_SIZE		32
+
+
+
+
+#define NUM_OF_BLOCKS                         0x0F  
+#define DTD_SIZE                              0x12  
+#define EDID_SIZE                             0x0100
+#define EDID_STRUCTURE_VERSION                0x12
+#define EDID_STRUCTURE_REVISION               0x13
+#define EDID_FEATURE_SUPPORT                  0x18
+#define EDID_ESTABLISHED_TIMINGS_1            0x23  
+#define EDID_ESTABLISHED_TIMINGS_2            0x24  
+#define EDID_MANUFACTURERS_RESERVED_TIMINGS   0x25  
+#define EDID_STANDARD_TIMINGS                 0x26  
+#define EDID_STANDARD_TIMINGS_BIT_DESCRIPTION 0x27  
+#define EDID_DETAILED_TIMING_DESCRIPTION_1    0x36  
+#define EDID_DETAILED_TIMING_DESCRIPTION_2    0x48  
+#define EDID_DETAILED_TIMING_DESCRIPTION_3    0x5A  
+
+#define EDID_EXTENSION_FLAG                   0x7E  
+
+#define EDID_CEA_TAG                          0x80  
+#define EDID_CEA_REVISION                     0x81  
+#define EDID_CEA_DETAILED_TIMING_DATA_OFFSET  0x82  
+#define EDID_CEA_VIDEO_DATA_BLOCK             0x84  
+#define EDID_CEA_DATA_BLOCK					  0x84
+
+#define EDID_CEA_VIDEO_DATA_BLOCK_2           0x96  
+#define EDID_CEA_VIDEO_DATA_BLOCK_3           0xA8  
+#define EDID_CEA_VIDEO_DATA_BLOCK_4           0xBA  
+#define EDID_CEA_VIDEO_DATA_BLOCK_5           0xCC  
+#define EDID_CEA_VIDEO_DATA_BLOCK_6           0xDE  
+
+#define EDID_SPACE_INDEX_START                0x18  
+
+
+
+
+
+typedef struct {
+    unsigned char  is_supported;
+    char mode_name[13];
+	unsigned long index[3]; 
+
+}established_timings_t, *p_established_timings;
+
+typedef struct {
+	unsigned int ha; 
+	unsigned int va; 
+	unsigned char refresh_rate;
+}standard_timings_t, *p_standard_timings;
+
+
+
+typedef struct {
+	unsigned char pclk_lobyte;
+	unsigned char pclk_hibyte;
+	unsigned char hactive_lobyte;
+	unsigned char hblank_lobyte;
+	unsigned char hactive_blank;			
+	unsigned char vactive_lobyte;
+	unsigned char vblank_lobyte;
+	unsigned char vactive_blank;			
+	unsigned char hsync_off_lobyte;			
+	unsigned char hsync_pulse_width;         
+	unsigned char vsync_off_pulse_width;	
+											
+	unsigned char hsopw_vsopw;				
+											
+											 
+											
+	unsigned char himage_size_lobyte;		
+	unsigned char vimage_size_lobyte;       
+	unsigned char hvimage_size;				
+											
+	unsigned char hborder;
+	unsigned char vborder; 
+	unsigned char flags;
+}dtd_t, *p_dtd;
+
+
+typedef struct monitor_range {
+
+	unsigned char  hrate_min;           
+	unsigned char  hrate_max;            
+	unsigned char  vrate_min;           
+	unsigned char  vrate_max;            
+
+	unsigned long  pclk_max;           
+
+}monitor_range_t;
+
+
+typedef struct detailed_timing_block {
+	unsigned long data_tag; 
+	OUT_FMT		dtiming; 
+} dtblks_t;
+
+
+typedef struct edid_blk {
+	
+
+	unsigned char						is_edid; 
+	unsigned char						is_preferred_timing;  
+
+	unsigned char						ebn; 
+	unsigned char						edidblk[EDID_SIZE]; 
+
+	established_timings_t				*etiming_I;
+	established_timings_t				*etiming_II;
+	established_timings_t				*etiming_man;
+
+	standard_timings_t					stiming[8];
+
+	standard_timings_t					stiming_x[6]; 
+	monitor_range_t						rtiming; 
+
+	dtblks_t							dtblk[4];
+	
+	
+	unsigned char						supported_modes[15]; 
+	ch7036_attr_table_index_t			modes[MAX_ATTR_LIST_SIZE]; 
+
+} ch7036_edid_blk_t;
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.c
new file mode 100755
index 0000000..5a842ab
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.c
@@ -0,0 +1,296 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file  ch7036_iic.c
+* @version 1.2.4
+*-----------------------------------------------------------------------------
+*/
+
+
+
+
+
+#include "ch7036_iic.h"
+#include "ch7036_def_regmap.h"
+
+
+static uint8 g_nCurPage = 0;
+static uint8 g_nCurRegmap[REG_PAGE_NUM][REG_NUM_PER_PAGE];
+
+int g_verbose = 0; 
+
+void DeviceReset(DEV_CONTEXT* pDevContext)
+{
+	
+	uint8 reg=0x00;
+
+   I2CWrite(pDevContext,0x03, 0x04);
+   
+   I2CWrite(pDevContext,0x52, 0x2B); 
+   I2CWrite(pDevContext,0x5a, 0x06);
+   I2CWrite(pDevContext,0x5a, 0x04);
+   I2CWrite(pDevContext,0x5a, 0x06);
+
+   I2CWrite(pDevContext,0x52, 0x29);
+   I2CWrite(pDevContext,0x52, 0x2b);
+
+   I2CWrite(pDevContext,0x5a, 0x04);
+
+  
+   I2CWrite(pDevContext,0x03, 0x01); 
+   reg = I2CRead(pDevContext,0x16);
+
+   reg = reg & 0xF7;
+   I2CWrite(pDevContext,0x16, reg);
+   
+
+
+}
+
+
+void DeviceSetup(DEV_CONTEXT* pDevContext)
+{
+	if (g_verbose) {
+			uint8 page, index;
+			uint16 k =0;       
+			uint16 rc[5];
+			for(page=0; page<REG_PAGE_NUM; ++page)
+			{
+				rc[page]=0;
+				if(page == 0x02) continue; 
+				I2CWrite(pDevContext,0x03, page); 
+				for(index=0x07; index<REG_NUM_PER_PAGE; ++index)
+				{
+					if(g_nCurRegmap[page][index] != g_DefRegMap[page][index])
+					{   
+			
+						k++;  
+						rc[page]++;
+						I2CWrite(pDevContext,index, g_nCurRegmap[page][index]);
+						
+					}
+				}
+			}
+	
+			for(page=0; page<REG_PAGE_NUM; ++page) 
+				
+				;
+
+	}
+	else {
+			uint8 page, index;
+			for(page=0; page<REG_PAGE_NUM; ++page)
+			{
+				if(page == 0x02) continue; 
+				I2CWrite(pDevContext,0x03, page);
+				for(index=0x07; index<REG_NUM_PER_PAGE; ++index)
+				{
+					if(g_nCurRegmap[page][index] != g_DefRegMap[page][index])
+					{
+						I2CWrite(pDevContext,index, g_nCurRegmap[page][index]);
+					}
+				}
+			}
+	}
+}
+
+
+uint8 iic_read(uint8 index)
+{
+	return g_nCurRegmap[g_nCurPage][index];
+}
+
+void iic_write(uint8 index, uint8 value)
+{
+	if(index == 0x03)
+	{
+		g_nCurPage = value;
+	}
+	else
+	{
+		g_nCurRegmap[g_nCurPage][index] = value;
+	}
+}
+
+void iic_reset()
+{
+	uint8 page, index;
+	for(page=0; page<REG_PAGE_NUM; ++page)
+	{
+		for(index=0; index<REG_NUM_PER_PAGE; ++index)
+		{
+			g_nCurRegmap[page][index] = g_DefRegMap[page][index];
+		}
+	}
+	g_nCurPage = 0x00; 
+}
+
+uint32 iic_read_ex(MULTI_REG_ID reg_id)
+{
+	uint8 oldpage;
+	uint32 n0, n1, n2, n3, mask, i, value;
+
+	
+	n0 = n1 = n2 = n3 = value = mask = 0;
+
+	
+	i = (uint32)reg_id;
+
+	
+	oldpage = iic_read(0x03);
+	iic_write(0x03, g_MultiRegTable[i].PageIndex);
+
+	if(NOOP_INDEX != g_MultiRegTable[i].TopRegIndex)
+		n0 = iic_read(g_MultiRegTable[i].TopRegIndex);
+
+	if(NOOP_INDEX != g_MultiRegTable[i].HighRegIndex) 
+		n1 = iic_read(g_MultiRegTable[i].HighRegIndex);
+
+	if(NOOP_INDEX != g_MultiRegTable[i].MiddleRegIndex)
+		n2 = iic_read(g_MultiRegTable[i].MiddleRegIndex);
+
+	n3 = iic_read(g_MultiRegTable[i].LowRegIndex);
+
+	iic_write(0x03, oldpage);
+
+	if(0 != n0)
+	{
+		mask = 1;
+		mask <<= g_MultiRegTable[i].TopEndBit - g_MultiRegTable[i].TopStartBit + 1;
+		mask -= 1;
+		mask <<= g_MultiRegTable[i].TopStartBit;
+		n0 &= mask;
+		n0 >>= g_MultiRegTable[i].TopStartBit;
+		n0 <<= (g_MultiRegTable[i].HighEndBit - g_MultiRegTable[i].HighStartBit + 1)+(g_MultiRegTable[i].MiddleEndBit - g_MultiRegTable[i].MiddleStartBit + 1) + (g_MultiRegTable[i].LowEndBit - g_MultiRegTable[i].LowStartBit + 1);
+	}
+	if(0 != n1)
+	{
+		mask = 1;
+		mask <<= g_MultiRegTable[i].HighEndBit - g_MultiRegTable[i].HighStartBit + 1;
+		mask -= 1;
+		mask <<= g_MultiRegTable[i].HighStartBit;
+		n1 &= mask;
+		n1 >>= g_MultiRegTable[i].HighStartBit;
+		n1 <<= (g_MultiRegTable[i].MiddleEndBit - g_MultiRegTable[i].MiddleStartBit + 1) + (g_MultiRegTable[i].LowEndBit - g_MultiRegTable[i].LowStartBit + 1);
+	}
+
+	if(0 != n2)
+	{
+		mask = 1;
+		mask <<= g_MultiRegTable[i].MiddleEndBit - g_MultiRegTable[i].MiddleStartBit + 1;
+		mask -= 1;
+		mask <<= g_MultiRegTable[i].MiddleStartBit;
+		n2 &= mask;
+		n2 >>= g_MultiRegTable[i].MiddleStartBit;	
+		n2 <<= g_MultiRegTable[i].LowEndBit - g_MultiRegTable[i].LowStartBit + 1;
+	}
+
+	if(0 != n3)
+	{
+		mask = 1;
+		mask <<= g_MultiRegTable[i].LowEndBit - g_MultiRegTable[i].LowStartBit + 1;
+		mask -= 1;
+		mask <<= g_MultiRegTable[i].LowStartBit;
+		n3 &= mask;
+		n3 >>= g_MultiRegTable[i].LowStartBit;
+	}
+
+	value = n0 | n1 | n2 | n3;
+	return value;
+}
+
+void iic_write_ex(MULTI_REG_ID reg_id, uint32 value)
+{
+	uint8 oldpage;
+	uint32 n1, n2, n3, n4, mask, nOrigin, i, value_local;
+
+	
+	n1 = n2 = n3 = n4 = mask = nOrigin = i = 0;
+	value_local = value;
+
+	
+	i = (uint32)reg_id;
+
+	
+	oldpage = iic_read(0x03);
+	iic_write(0x03, g_MultiRegTable[i].PageIndex);
+
+	mask = 1;
+	mask <<= g_MultiRegTable[i].LowEndBit - g_MultiRegTable[i].LowStartBit + 1;
+	mask -= 1;
+	n1 = value_local & mask;
+	n1 <<= g_MultiRegTable[i].LowStartBit;
+	nOrigin = iic_read(g_MultiRegTable[i].LowRegIndex);
+	mask <<= g_MultiRegTable[i].LowStartBit;
+	nOrigin &= ~mask;
+	n1 |= nOrigin;
+	iic_write(g_MultiRegTable[i].LowRegIndex, (uint8)n1);
+	value_local >>= g_MultiRegTable[i].LowEndBit - g_MultiRegTable[i].LowStartBit + 1;
+
+	if(NOOP_INDEX != g_MultiRegTable[i].MiddleRegIndex)
+	{
+		mask = 1;
+		mask <<= g_MultiRegTable[i].MiddleEndBit - g_MultiRegTable[i].MiddleStartBit + 1;
+		mask -= 1;
+		n2 = value_local & mask;
+		n2 <<= g_MultiRegTable[i].MiddleStartBit;
+		nOrigin = iic_read(g_MultiRegTable[i].MiddleRegIndex);
+		mask <<= g_MultiRegTable[i].MiddleStartBit;
+		nOrigin &= ~mask;
+		n2 |= nOrigin;
+		iic_write(g_MultiRegTable[i].MiddleRegIndex, (uint8)n2);
+		value_local >>= g_MultiRegTable[i].MiddleEndBit - g_MultiRegTable[i].MiddleStartBit + 1;
+
+		if(NOOP_INDEX != g_MultiRegTable[i].HighRegIndex)
+		{
+			mask = 1;
+			mask <<= g_MultiRegTable[i].HighEndBit - g_MultiRegTable[i].HighStartBit + 1;
+			mask -= 1;
+			n3 = value_local & mask;
+			n3 <<= g_MultiRegTable[i].HighStartBit; 
+			nOrigin = iic_read(g_MultiRegTable[i].HighRegIndex);
+			mask <<= g_MultiRegTable[i].HighStartBit;
+			nOrigin &= ~mask;
+			n3 |= nOrigin;
+			iic_write(g_MultiRegTable[i].HighRegIndex, (uint8)n3);
+			value_local >>= g_MultiRegTable[i].HighEndBit - g_MultiRegTable[i].HighStartBit + 1;
+
+			if(NOOP_INDEX != g_MultiRegTable[i].TopRegIndex)
+			{
+				mask = 1;
+				mask <<= g_MultiRegTable[i].TopEndBit - g_MultiRegTable[i].TopStartBit +1;
+				mask -= 1;
+				n4 = value_local & mask;
+				n4 <<= g_MultiRegTable[i].TopStartBit;
+				nOrigin = iic_read(g_MultiRegTable[i].TopRegIndex);
+				mask <<= g_MultiRegTable[i].TopStartBit;
+				nOrigin &= ~mask;
+				n4 |= nOrigin;
+				iic_write(g_MultiRegTable[i].TopRegIndex,(uint8)n4);
+			}
+		}		
+	}
+
+	iic_write(0x03, oldpage);
+}
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.h
new file mode 100755
index 0000000..593aee8
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_iic.h
@@ -0,0 +1,52 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file  ch7036_iic.h
+* @version 1.2.2
+*-----------------------------------------------------------------------------
+*/
+
+#ifndef _CH7036_IIC_H
+#define _CH7036_IIC_H
+
+#include "ch7036_typedef.h"
+#include "ch7036_reg_table.h"
+
+
+
+
+uint8 I2CRead(DEV_CONTEXT* pDevContext, uint8 index);
+void I2CWrite(DEV_CONTEXT* pDevContext, uint8 index, uint8 value);
+
+void I2CBlockWrite(DEV_CONTEXT* pDevContext,uint8 index, uint8* value, uint16 len);
+void DeviceReset(DEV_CONTEXT* pDevContext);
+void DeviceSetup(DEV_CONTEXT* pDevContext);
+
+uint8 iic_read(uint8 index);
+void iic_write(uint8 index, uint8 value);
+void iic_reset(void);
+uint32 iic_read_ex(MULTI_REG_ID reg_id);
+void iic_write_ex(MULTI_REG_ID reg_id, uint32 reg_val);
+
+extern int g_verbose;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.c
new file mode 100644
index 0000000..bc7b8a9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.c
@@ -0,0 +1,1994 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file  ch7036_intf.c
+* @version 1.2.5
+*-----------------------------------------------------------------------------
+*/
+
+
+#include "ch7036_intf.h"
+#include "ch7036_attr.h"
+
+
+#ifdef T_LINUX
+	#include "lvds/lvds.h"
+#else
+	#include "lvds.h"
+#endif
+
+
+ch7036_status_t ch7036_get_hdmi_hpd(ch7036_device_context_t* p_ctx, uint8 *hpd);
+
+unsigned long ch7036_invis_6x4_modes_table_size[3] = {2,3,5}; 
+unsigned long ch7036_invis_8x6_7x4_table_size[3] = {3,5,6};
+
+OUT_FMT hdmi_timing_table[OUT_HDMI_END] = {
+	
+		                    
+	{1,     25175,  1, {800,   640, 16,  96, 525,  480, 10,  2, 59, SCANTYPE_PROGRESSIVE} }, 
+    {1,     25250,  1, {800,   640, 16,  96, 525,  480, 10,  2, 60, SCANTYPE_PROGRESSIVE} },
+    {2,     27000,  1, {858,   720, 16,  62, 525,  480,  9,  6, 59, SCANTYPE_PROGRESSIVE} },
+    {2,     27027,  1, {858,   720, 16,  62, 525,  480,  9,  6, 60, SCANTYPE_PROGRESSIVE} },
+	{17,     27000,  1, {864,  720,  12,  64, 625,  576,  5,  5, 50, SCANTYPE_PROGRESSIVE} },
+
+    {4,     74176,  2, {1650, 1280, 110, 40, 750,  720,  5,  5, 59, SCANTYPE_PROGRESSIVE} },
+    {4,     74250,  2, {1650, 1280, 110, 40, 750,  720,  5,  5, 60, SCANTYPE_PROGRESSIVE} },
+    {5,     74176,  2, {2200, 1920, 88,  44, 1125, 1080, 2,  5, 59, SCANTYPE_INTERLACED} },
+    {5,     74250,  2, {2200, 1920, 88,  44, 1125, 1080, 2,  5, 60, SCANTYPE_INTERLACED} },
+	{16,    148350,  2, {2200, 1920, 88,  44, 1125, 1080, 4,  5, 59, SCANTYPE_PROGRESSIVE} },
+//   {16,    148352,  2, {2200, 1920, 88,  44, 1125, 1080, 4,  5, 59, SCANTYPE_PROGRESSIVE} }, 
+   {16,    148500,  2, {2200, 1920, 88,  44, 1125, 1080, 4,  5, 60, SCANTYPE_PROGRESSIVE} }, 
+ 
+//   {17,     27000,  1, {864,  720,  12,  64, 625,  576,  5,  5, 50, SCANTYPE_PROGRESSIVE} }, 
+   {19,     74250,  2, {1980, 1280, 440, 40, 750,  720,  5,  5, 50, SCANTYPE_PROGRESSIVE} }, 
+   
+   {20,     74250,  2, {2640, 1920, 528, 44, 1125, 1080, 2, 5, 50, SCANTYPE_INTERLACED} },
+
+
+   {31,    148500,  2, {2640, 1920, 528, 44, 1125, 1080, 4,  5, 50, SCANTYPE_PROGRESSIVE} },
+   {32,     74175,  2, {2750, 1920, 638, 44, 1125, 1080, 4,  5, 23, SCANTYPE_PROGRESSIVE} },
+   {32,     74250,  2, {2750, 1920, 638, 44, 1125, 1080, 4,  5, 24, SCANTYPE_PROGRESSIVE} },
+   {33,     74250,  2, {2640, 1920, 528, 44, 1125, 1080, 4,  5, 25, SCANTYPE_PROGRESSIVE} },
+   {34,     74175,  2, {2200, 1920, 88,  44, 1125, 1080, 4,  5, 29, SCANTYPE_PROGRESSIVE} },
+   {34,     74250,  2, {2200, 1920, 88,  44, 1125, 1080, 4,  5, 30, SCANTYPE_PROGRESSIVE} }, 
+
+   {40,    148500,  2, {2640, 1920, 528, 44, 1124, 1080, 4, 10, 100, SCANTYPE_INTERLACED} },
+   {41,    148500,  2, {1980, 1280, 440, 40, 750,  720,  5,  5, 100, SCANTYPE_PROGRESSIVE} },
+   {42,     54000,  1, {864,   720, 12,  64, 625,  576,  5,  5, 100, SCANTYPE_PROGRESSIVE} },
+
+
+   {46,    148352,  2, {2200, 1920, 88,  44, 1124, 1080, 4, 10, 119, SCANTYPE_INTERLACED} },
+   {46,    148500,  2, {2200, 1920, 88,  44, 1124, 1080, 4, 10, 120, SCANTYPE_INTERLACED} },
+
+   {47,    148352,  2, {1650, 1280, 110, 40, 750,  720,  5,  5, 119, SCANTYPE_PROGRESSIVE} },
+   {47,    148500,  2, {1650, 1280, 110, 40, 750,  720,  5,  5, 120, SCANTYPE_PROGRESSIVE} },
+   
+   {48,     54000,  1, {858,   720, 16,  62, 525,  480,  9,  6, 119, SCANTYPE_PROGRESSIVE} },
+   {48,     54054,  1, {858,   720, 16,  62, 525,  480,  9,  6, 120, SCANTYPE_PROGRESSIVE} }, 
+  
+   {52,    108000,  1, {864,   720, 12,  64, 625,  576,  5,  5, 200, SCANTYPE_PROGRESSIVE} },
+
+   {56,    108000,  1, {858,   720, 16,  62, 525,  480,  9,  6, 239, SCANTYPE_PROGRESSIVE} },
+   {56,    108108,  1, {858,   720, 16,  62, 525,  480,  9,  6, 240, SCANTYPE_PROGRESSIVE} }, 
+  
+};
+
+OUT_FMT dvi_timing_table[OUT_DVI_END] = {
+	
+
+
+	{0,     25170,  0, { 800,  640, 16,  96, 525,  480, 10,  2,  60, SCANTYPE_PROGRESSIVE}	}, 
+	{0,     31500,  0, { 832,  640, 24,  40, 520,  480,  9,  3,  72, SCANTYPE_PROGRESSIVE}	},  
+    {0,     31500,  0, { 800,  640, 16,  96, 525,  480, 11,  2,  75, SCANTYPE_PROGRESSIVE}	},  
+
+	{0,     28322,  0, { 900,  720, 15, 108, 449,  400, 11,  2,  70, SCANTYPE_PROGRESSIVE}	},  
+	
+	{0,		38100,	0, {1088,  800,	32, 128, 619,  600,  1,  4,  56, SCANTYPE_PROGRESSIVE}	},
+	
+
+	{0,		40000,	0, {1056,  800,	40, 128, 628,  600,  1,  4,  60, SCANTYPE_PROGRESSIVE}	},
+	{0,		50000,	0, {1040,  800,	56, 120, 666,  600, 37,  6,  72, SCANTYPE_PROGRESSIVE}	},
+	{0,		49500,	0, {1056,  800,	16,  80, 624,  600,  1,  2,  75, SCANTYPE_PROGRESSIVE}	},
+
+	{0,		65000,	0, {1344, 1024,	24,	136, 806,  768,	 3,	 6,  60, SCANTYPE_PROGRESSIVE}	}, 
+    {0,		75000,	0, {1328, 1024,	24,	136, 806,  768,	 3,	 6,  70, SCANTYPE_PROGRESSIVE}	},
+	{0,		78750,	0, {1312, 1024,	16,	 96, 800,  768,	 1,	 3,  75, SCANTYPE_PROGRESSIVE}	},
+
+	{0,		81517,	0, {1688, 1152,	48,112,1066,  864,	 1,	 3,  60, SCANTYPE_PROGRESSIVE}	},
+
+	{0,		83460,	0, {1680, 1280,	64,	136, 828,  720,  1,	 3,  60, SCANTYPE_PROGRESSIVE}	}, 
+	
+	{0,		83865,	0, {1680, 1280,	64,	136, 828,  800,  1,	 3,  60, SCANTYPE_PROGRESSIVE}	},
+	
+	{0,		100638,	0, {1688, 1280,	48,	112, 1066, 960,  1,	 3,  60, SCANTYPE_PROGRESSIVE}	},
+
+	{0,		108000,	0, {1688, 1280,	48,	112, 1066, 1024, 1,	 3,  60, SCANTYPE_PROGRESSIVE}	}, 
+	{0,		135000,	0, {1688, 1280,	16,	144, 1066, 1024, 1,	 3,  75, SCANTYPE_PROGRESSIVE}	},
+
+	{0,		85543,	0, {2256, 1360,104, 184, 1087, 768,  1,	 3,  60, SCANTYPE_PROGRESSIVE}	},
+	{0,		85920,	0, {2256, 1366,104, 184, 1087, 768,  1,	 3,  60, SCANTYPE_PROGRESSIVE}	},
+
+	{0,		121750,	0, {1864, 1400,	88,144,1089,  1050,	 3,	 4,  60, SCANTYPE_PROGRESSIVE}	}, 
+    {0,		156000,	0, {1896, 1400,104,144,1099,  1050,	 3,	 4,  75, SCANTYPE_PROGRESSIVE}	},
+
+
+	{0,		88750,	0, {1600, 1440,	48,	32,	 926,  900,	 3,	 6,  60, SCANTYPE_PROGRESSIVE}	},
+	{0,		119000,	0, {1840, 1440,	48,	32,	 1080, 1050, 3,	 6,  60, SCANTYPE_PROGRESSIVE}	},
+ 	
+	{0,		117936,	0, {2256, 1600,104,	184, 1250,  900, 1,	 3,  60, SCANTYPE_PROGRESSIVE}	},
+	{0,		162000,	0, {2160, 1600,	64,	192, 1250, 1200, 1,	 3,  60, SCANTYPE_PROGRESSIVE}	},
+
+	{0,		147130,	0, {2256, 1680,104,	184, 1087, 1050, 1,	 3,  60, SCANTYPE_PROGRESSIVE}	},
+	{0,     148500, 0, {2200, 1920, 88,  44, 1125, 1080, 4,  5, 60, SCANTYPE_PROGRESSIVE} },
+	{0,		154000,	0, {2080, 1920,	48,	 32, 1235, 1200, 3,	 6,  60, SCANTYPE_PROGRESSIVE}	},
+
+};
+
+
+
+
+OUT_FMT ch7036_crt_timing_table[OUT_CRT_END] = {
+   
+   
+   {100,    31500,  1, {832,   640, 32,  64,  445,  400, 1,  3,  85, SCANTYPE_PROGRESSIVE}  },
+	 
+   {100,    25175,  1, {800,   640,  8,  96,  525,  480, 2,  2,  60, SCANTYPE_PROGRESSIVE}  },
+   {100,    31500,  1, {832,   640, 16,  40,  520,  480, 1,  3,  72, SCANTYPE_PROGRESSIVE}  },
+   {100,    31500,  1, {840,   640, 16,  64,  500,  480, 1,  3,  75, SCANTYPE_PROGRESSIVE}  },
+   {100,    36000,  1, {832,   640, 56,  56,  509,  480, 1,  3,  85, SCANTYPE_PROGRESSIVE}  },
+   
+   {100,    35500,  1, {936,   720, 36,  72,  446,  400, 1,  3,  85, SCANTYPE_PROGRESSIVE}  },
+   
+
+   
+   {100,    36000,  1, {1024,  800, 24,  72,  625,  600, 1,  2,  56, SCANTYPE_PROGRESSIVE}  },
+   
+
+   {100,    38250,  1, {1024,  800, 32,  80,  624,  600, 3,  4,  60, SCANTYPE_PROGRESSIVE}  },
+   {100,    50000,  1, {1040,  800, 56, 120,  666,  600, 37, 6,  72, SCANTYPE_PROGRESSIVE}  },
+   {100,    49000,  1, {1040,  800, 40,  80,  629,  600, 3,  4,  75, SCANTYPE_PROGRESSIVE}  },
+   {100,    56750,  1, {1056,  800, 48,  80,  633,  600, 3,  4,  85, SCANTYPE_PROGRESSIVE}  },
+
+    
+   {100,    65000,  1, {1344, 1024, 24, 136,  806,  768, 3,  6,  60, SCANTYPE_PROGRESSIVE}  },
+   {100,    75000,  1, {1328, 1024, 24, 136,  806,  768, 3,  6,  70, SCANTYPE_PROGRESSIVE}  },
+   {100,    78750,  1, {1312, 1024, 16,  96,  800,  768, 1,  3,  75, SCANTYPE_PROGRESSIVE}  }, 
+   
+   {100,    94500,  1, {1376, 1024, 48,  96,  808,  768, 1,  3,  85, SCANTYPE_PROGRESSIVE}  },
+   
+    
+   {100,   108000,  1, {1600, 1152, 64, 128,  900,  864, 1,  2,  75, SCANTYPE_PROGRESSIVE}  },
+
+   
+   {100,    79500,  1, {1664, 1280, 64, 128,  798,  768, 3,  7,  60, SCANTYPE_PROGRESSIVE}  },
+   {100,   102250,  1, {1696, 1280, 80, 128,  805,  768, 3,  7,  75, SCANTYPE_PROGRESSIVE}  },
+   {100,   117500,  1, {1712, 1280, 80, 136,  809,  768, 3,  7,  85, SCANTYPE_PROGRESSIVE}  },
+  
+   
+   {100,   108000,  1, {1800, 1280, 96, 112, 1000,  960, 1,  3,  60, SCANTYPE_PROGRESSIVE}  },
+   {100,   148500,  1, {1728, 1280, 64, 160, 1011,  960, 1,  3,  85, SCANTYPE_PROGRESSIVE}  },
+
+    
+   {100,   108000,  1, {1688, 1280, 48, 112, 1066, 1024, 1,  3,  60, SCANTYPE_PROGRESSIVE}  },
+   {100,   135000,  1, {1688, 1280, 16, 144, 1066, 1024, 1,  3,  75, SCANTYPE_PROGRESSIVE}  },
+   {100,   157500,  1, {1728, 1280, 64, 160, 1072, 1024, 1,  3,  85, SCANTYPE_PROGRESSIVE}  },
+
+   
+   {100,    85500,	1, {1792, 1360,	64, 112,  795,  768, 3,	 6,  60, SCANTYPE_PROGRESSIVE}	},
+
+   
+   {100,   121750,	1, {1864, 1400,	88,144,1089,  1050,	 3,	 4,  60, SCANTYPE_PROGRESSIVE}	},
+   {100,   156000,	1, {1896, 1400,104,144,1099,  1050,	 3,	 4,  75, SCANTYPE_PROGRESSIVE}	},
+
+   
+   {100,	88750,	1, {1600, 1440,	48,	32,	 926,  900,	 3,	 6,  60, SCANTYPE_PROGRESSIVE}	},
+
+   
+   {100,   119000,	1, {1840, 1440,	48,	32,	 1080, 1050, 3,	 6,  60, SCANTYPE_PROGRESSIVE}	},
+
+   
+   {100,   117936,	1, {2256, 1600,104,	184, 1250,  900, 1,	 3,  60, SCANTYPE_PROGRESSIVE}	},
+   
+   
+   {100,   162000,  1, {2160, 1600, 64, 192, 1250, 1200, 1,  3,  60, SCANTYPE_PROGRESSIVE}  },
+   
+   
+   
+   {100,   148500, 1, {2200, 1920, 88,  44, 1125, 1080, 4,  5, 60, SCANTYPE_PROGRESSIVE} },
+   
+   
+   
+};
+
+
+
+
+
+uint8 I2CRead(DEV_CONTEXT* pDevContext,uint8 index)
+{	
+	
+	ch7036_device_context_t *p_ctx= pDevContext->pd_context;
+	pd_reg_t reg_list[2];
+
+	reg_list[0].reg = (i2c_reg_t)index;
+	reg_list[1].reg = PD_REG_LIST_END;
+
+	p_ctx->p_callback->read_regs(p_ctx->p_callback->callback_context, reg_list,PD_REG_DDC);
+
+	return (uint8)(reg_list[0].value);
+}
+
+void I2CWrite(DEV_CONTEXT* pDevContext,uint8 index, uint8 value)
+{
+	ch7036_device_context_t *p_ctx= pDevContext->pd_context;
+	pd_reg_t reg_list[2];
+
+	
+
+	reg_list[0].reg = (i2c_reg_t)index;
+	reg_list[0].value = (i2c_reg_t)value;
+
+	reg_list[1].reg = PD_REG_LIST_END;
+
+	p_ctx->p_callback->write_regs(p_ctx->p_callback->callback_context, reg_list,PD_REG_DDC);
+
+	return;
+}
+
+
+void I2CBlockWrite(DEV_CONTEXT* pDevContext,uint8 index, uint8* value, uint16 len)
+{
+	ch7036_device_context_t *p_ctx= pDevContext->pd_context;
+	pd_reg_t reg_list[MAX_I2C_BLOCK_SIZE +1]; 
+	uint16 i=0;
+	
+
+	for(i=0;i<len;i++) {
+		reg_list[i].reg = (i2c_reg_t)index;
+		reg_list[i].value = (i2c_reg_t)value[i];
+	}
+
+	reg_list[len].reg = PD_REG_LIST_END;
+
+	p_ctx->p_callback->write_regs(p_ctx->p_callback->callback_context, reg_list,PD_REG_DDC);
+
+	return;
+}
+
+ch7036_status_t ch7036_device_prepare(ch7036_device_context_t* p_ctx)
+{
+	DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
+	ch7036_status_t status = SS_SUCCESS;
+
+	PD_DEBUG("ch7036_intf: ch7036_device_prepare()\n");
+
+
+	if(!DevicePrepare(p_ch_ctx))
+	{
+		p_ctx->last_emsg = GetLastErrorMessage(); 
+		status = SS_UNSUCCESSFUL; 
+	}
+	
+	return status;
+}
+
+ch7036_status_t ch7036_device_config(ch7036_device_context_t* p_ctx)
+{
+	DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
+	ch7036_status_t status = SS_SUCCESS;
+
+	PD_DEBUG("ch7036_intf: ch7036_device_config()\n");
+
+	
+	if(!DeviceConfig(p_ch_ctx))
+	{
+		p_ctx->last_emsg = GetLastErrorMessage();
+		status = SS_UNSUCCESSFUL;
+	}
+	
+	return status;
+	
+}
+
+ch7036_status_t ch7036_device_start(ch7036_device_context_t* p_ctx)
+{
+	
+	DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
+	ch7036_status_t status = SS_SUCCESS;
+
+	PD_DEBUG("ch7036_intf: ch7036_device_start()\n");
+	
+	if(!DeviceRunning(p_ch_ctx))
+	{
+		p_ctx->last_emsg = GetLastErrorMessage();
+		status = SS_UNSUCCESSFUL;
+	}
+	
+	return status;
+	
+}
+
+ch7036_status_t ch7036_device_set_power(ch7036_device_context_t* p_ctx, unsigned long channel)
+{
+	DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
+	ch7036_status_t status = SS_SUCCESS;
+
+	PD_DEBUG("ch7036_intf: ch7036_device_set_power()- channel [%x]\n", channel);
+	
+	if(!DeviceSetPower(p_ch_ctx,channel))
+	{
+		p_ctx->last_emsg = GetLastErrorMessage();
+		status = SS_UNSUCCESSFUL;
+	}
+	
+	return status;
+}
+
+
+
+ch7036_status_t ch7036_load_firmware(ch7036_device_context_t* p_ctx)
+{
+	
+	DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
+
+	ch7036_status_t status = SS_UNSUCCESSFUL;
+
+	PD_DEBUG("ch7036: ch7036_load_firmware()\n");
+
+	
+	if(LHFM_load_firmware(p_ch_ctx) == -1) {
+		PD_DEBUG("ch7036_load_firmware: LHFM_load_firmware()- firmware loading FAILED...\n");
+		
+	}
+	else  {
+		PD_DEBUG("ch7036_load_firmware: LHFM_load_firmware()- firmware loading is a SUCCESS\n");
+		status = SS_SUCCESS;
+	}
+	
+
+	return status;
+
+}
+
+
+
+
+
+
+ch7036_status_t ch7036_get_hdvi_display_modes_supported(ch7036_device_context_t* p_ctx) 
+{
+	DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+	ch7036_status_t status;
+	ch7036_edid_blk_t* p_hedid = (ch7036_edid_blk_t *)p_ctx->hedid;
+
+
+	PD_DEBUG("ch7036_get_hdvi_display_modes_supported()- enter\n");
+
+	status = LHFM_get_hdmi_modeinfo(p_ch7xxx_context,p_hedid->supported_modes);
+
+	if (status == SS_SUCCESS) {
+
+		PD_DEBUG("HDMI_Modes=%02X. Vesa_Modes=%02x\r\n", p_hedid->supported_modes[13], p_hedid->supported_modes[14]);
+
+						
+	}
+	else {
+		PD_DEBUG("ch7036_get_hdvi_display_modes_supported()-- failed!\r\n");
+		PD_DEBUG("status: [%s]\n",status == SS_FIRMWARE_TIMEOUT?"timeout!":"firmware_error!");
+
+		
+	}
+	
+	return status;
+}
+
+
+
+ch7036_status_t ch7036_read_edid(ch7036_device_context_t* p_ctx, uint32 channel)
+{
+	
+	DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+	OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+	ch7036_status_t status = SS_UNSUCCESSFUL; 
+	
+
#ifdef T_CH7036_EDID_DUMP
+	uint8 ebn;
+	int i;
+#endif
+
+	ch7036_edid_blk_t* p_hedid = (ch7036_edid_blk_t *)p_ctx->hedid;
+	ch7036_edid_blk_t* p_cedid = (ch7036_edid_blk_t *)p_ctx->cedid;
+
+
+	unsigned char* hedidblk = p_hedid->edidblk;
+	unsigned char* cedidblk = p_cedid->edidblk;
+
+
+
+	switch (channel) {
+
+		case CHANNEL_LVDS_HDMI:
+		case CHANNEL_HDMI:
+
+			
+			status = LHFM_get_edid(p_ch7xxx_context,hedidblk, &(p_hedid->ebn), CH7036_HDMI_DDC);
+
+			if(status == SS_SUCCESS) {	
+			
+				PD_DEBUG("ch7036_read_edid()-hdmi-dvi hpd status- attached, hdmi-dvi edid read is a SUCCESS\n");
+				PD_DEBUG("ch7036_read_edid()- number of blocks read [%x]\n", p_hedid->ebn);
+			
+				p_hedid->is_edid = 1;
+				if(p_hedid->ebn == 1)  
+					pOutput_Info->hdmi_fmt.is_dvi_mode =1;
+							
+				else 
+					pOutput_Info->hdmi_fmt.is_dvi_mode =0;
+				
+
+		
+#ifdef T_CH7036_EDID_DUMP
+	
+				if (p_hedid->ebn <= MAX_EDID_BLOCKS) { 
+					for (i=0; i<p_hedid->ebn; i++) 
+						ch7036_dump("HDMI-DVI EDID Data", 128, &hedidblk[i*128]);
+								
+				}
+
+#endif
+
+			} 
+
+			else { 
+				p_hedid->is_edid = 0;
+				
+				status = SS_UNSUCCESSFUL;
+
+			}	
+
+			break;
+
+		case CHANNEL_LVDS_VGA:
+		case CHANNEL_VGA:
+			
+			I2CWrite(p_ch7xxx_context,0x03, 0x01);			
+			I2CWrite(p_ch7xxx_context,0x0F, I2CRead(p_ch7xxx_context,0x0F) & 0x7F);		
+			pd_usleep(200);
+
+			status = LHFM_get_edid(p_ch7xxx_context,cedidblk, &(p_cedid->ebn), CH7036_VGA_DDC);
+			if (status== SS_SUCCESS) {
+				p_cedid->is_edid =1;
+				PD_DEBUG("ch7036_read_edid()- crt hpd status- attached, crt edid read is a SUCCESS\n");
+				PD_DEBUG("ch7036_read_edid()- number of blocks read [%x]\n", p_cedid->ebn);
+
+#ifdef T_CH7036_EDID_DUMP
+				if (p_cedid->ebn <= MAX_EDID_BLOCKS) 
+					for (i=0; i<p_cedid->ebn; i++) 
+						ch7036_dump("VGA EDID Data", 128, &cedidblk[i*128]);
+
+
+#endif
+
+			}
+			else {
+				p_cedid->is_edid =0;
+					
+				status = SS_UNSUCCESSFUL;
+			}
+
+	
+			break;
+
+		default:
+			break;
+
+
+	} 
+
+
+	return status;
+}
+
+ch7036_status_t ch7036_get_hdmi_hpd(ch7036_device_context_t* p_ctx, uint8 *hpd)
+{
+	DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+	ch7036_status_t status= SS_SUCCESS;
+	unsigned char reg, reg_hpdpw;
+
+	I2CWrite(p_ch7xxx_context,0x03, 0x03);
+	reg = I2CRead(p_ch7xxx_context,0x25);
+
+	I2CWrite(p_ch7xxx_context,0x03, 0x04);
+	reg_hpdpw = I2CRead(p_ch7xxx_context,0x51);
+
+#ifdef T_CONFIG_PLB	
+	if(!(reg & 0x10) && (reg_hpdpw & 0x80) ){
+		reg= 0x10;
+	}
+#endif
+
+	switch (reg & 0x10) {
+		case 0x10:
+			if(p_ctx->hpd & CH7036HPD_HDVI_ATTACHED)
+				*hpd = 0x01;
+			else
+				*hpd = 0x81;
+			break;
+		case 0x00:
+			if(p_ctx->hpd & CH7036HPD_HDVI_ATTACHED)
+				*hpd = 0x80;
+			else
+				*hpd = 0x00;
+			break;
+	}
+	
+
+	PD_DEBUG("ch7036: ch7036_get_hdmi_hpd- exit...*hpd [0x%x]\n",*hpd);
+
+	return status;
+
+}
+ch7036_status_t ch7036_get_attached_device(ch7036_device_context_t* p_ctx)
+{
+	DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+	OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+	uint8 reg;
+	ch7036_status_t status = SS_SUCCESS;
+	ch7036_status_t status_hdmi, status_crt;
+
+	ch7036_edid_blk_t * p_hedid = (ch7036_edid_blk_t *)(p_ctx->hedid);
+
+	uint8 hpd = 0;
+
+
+	
+	I2CWrite(p_ch7xxx_context,0x03, 0x04);
+	reg = I2CRead(p_ch7xxx_context,0x52);
+	
+	reg = reg & 0xEF; 
+	I2CWrite(p_ch7xxx_context,0x52, reg);
+
+	
+	I2CWrite(p_ch7xxx_context,0x03, 0x0);
+	reg = I2CRead(p_ch7xxx_context,0x07);
+	
+	reg = reg & 0x70; 
+	I2CWrite(p_ch7xxx_context,0x07, reg);
+	
+	I2CWrite(p_ch7xxx_context,0x03, 0x01);
+	reg = I2CRead(p_ch7xxx_context,0x0F);
+	
+	reg = reg & 0x7F; 	
+	I2CWrite(p_ch7xxx_context,0x0F, reg); 
+
+	I2CWrite(p_ch7xxx_context,0x0E, I2CRead(p_ch7xxx_context,0x0E) & 0x7F);
+		
+	PD_DEBUG("ch7036_get_attached_device()- enter- p_ctx->hpd= [0x%x]\n", p_ctx->hpd);
+
+	status_hdmi = ch7036_get_hdmi_hpd(p_ctx,&hpd);
+	LHFM_enable_crt_hpd(p_ch7xxx_context);  
+	status_crt = LHFM_get_crt_hpd(p_ch7xxx_context);
+
+	PD_DEBUG("ch7036_get_attached_device()- enter- pOutput_Info->channel = [0x%x]\n", pOutput_Info->channel);
+	
+	if(p_ctx->man_sel_out==1) { //manual selection
+
+		
+		if( (status_crt == SS_SUCCESS) || ( (hpd & 0x01)== 1 ) ) { 
+
+			switch (pOutput_Info->channel) {				
+				case CHANNEL_LVDS_DVI: 
+				case CHANNEL_DVI: 
+				case CHANNEL_LVDS_HDMI:
+				case CHANNEL_HDMI: 
+
+					 
+					if( (status_crt == SS_SUCCESS) && ( (hpd & 0x01)== 0 ) ) { 
+
+						p_ctx->hpd = 0x16; //bit 4=1 to indicate SS_DISPLAY_CHOICE_NOT_ALLOWED,  check edid and parse it												
+						status = SS_DISPLAY_CHOICE_NOT_ALLOWED;
+
+					}
+					else {
+
+						if (!p_ctx->init_done || ((p_ctx->prev_outchannel & pOutput_Info->channel) & 0x02) != 0x02 ) 
+							p_ctx->hpd = 0x60;
+						else 
+							p_ctx->hpd = ( ((p_ctx->prev_outchannel & pOutput_Info->channel) & 0x02) == 0x02)?0xA0:0x60;							
+											
+						status = SS_SUCCESS;
+					}
+										
+					break;
+
+				case CHANNEL_LVDS_VGA: 
+				case CHANNEL_VGA:
+					
+					
+					if((status_crt != SS_SUCCESS) && ((hpd & 0x01)==1 ) ) { 
+						
+						if(!p_ctx->init_done) { 
+							p_ctx->hpd = 0x06; 
+							status = SS_SUCCESS;
+							
+						}else {					
+							p_ctx->hpd = (hpd & 0x80)?0x70:0x30; 
+							status = SS_DISPLAY_CHOICE_NOT_ALLOWED;
+						}
+						
+					}
+					else { 
+
+						if ( (!p_ctx->init_done) || ((p_ctx->prev_outchannel & pOutput_Info->channel) & 0x04) != 0x04 )//at init, need to read edid, and parse it
+							p_ctx->hpd = 0x06;
+						else {							
+							p_ctx->hpd = ( ((p_ctx->prev_outchannel & pOutput_Info->channel) & 0x04) == 0x04)?0x0A:0x06;
+													
+						}
+
+						status = SS_SUCCESS;
+					}
+															
+					break;
+			} //switch
+
+			if(status == SS_DISPLAY_CHOICE_NOT_ALLOWED)
+				PD_DEBUG("ch7036_get_attached_device()- manual selection- display choice is not allowed...\n");
+
+		}
+		else {
+			
+			if (!p_ctx->init_done) { 
+				p_ctx->hpd = 0x06; 
+				status = SS_SUCCESS;
+				
+			}else {
+
+				PD_DEBUG("ch7036_get_attached_device()- manual selection- none is connected- not allowed...\n");
+				
+				status = SS_DISPLAY_CHOICE_NOT_ALLOWED;
+				p_ctx->hpd = 0x50;
+
+			}
+
+
+		}
+
+		PD_DEBUG("ch7036_get_attached_device()- manual selection- exit- p_ctx->hpd= [0x%x]\n", p_ctx->hpd);
+		PD_DEBUG("ch7036_get_attached_device()- exit- pOutput_Info->channel = [0x%x]\n", pOutput_Info->channel);
+
+		I2CWrite(p_ch7xxx_context,0x03, 0x03);
+		reg = I2CRead(p_ch7xxx_context,0x25);
+
+		PD_DEBUG("ch7036_get_attached_device()- manual selection- exit...HPD_MCU [0x%x]\n",reg);
+
+		return status;
+	}
+
+	//auto detection 
+
+	if(status_hdmi == SS_SUCCESS) { 
+			
+			if( hpd == 0x81 ) { 
+				if(p_ctx->hpd & CH7036HPD_HDVI_ATTACHED)  {
+
+					p_ctx->hpd = (p_ctx->hpd  & 0x9F) & ((~CH7036HPD_HDVI_STATUS_CHANGED) | CH7036HPD_HDVI_ATTACHED); 
+										
+					ch7036_get_hdvi_display_modes_supported(p_ctx);
+				
+					if ( 
+						((pOutput_Info->hdmi_fmt.is_dvi_mode== 0) && (p_hedid->supported_modes[13] == 0) )||
+						((pOutput_Info->hdmi_fmt.is_dvi_mode== 1) && (p_hedid->supported_modes[13] > 0))
+					) {
+
+						p_ctx->hpd = (p_ctx->hpd  & 0x9F) | (CH7036HPD_HDVI_STATUS_CHANGED | CH7036HPD_HDVI_ATTACHED);
+						PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status changed [HDMI<->DVI] since last query and it's HIGH\n");
+
+					}
+					else					
+						PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status has not changed since last query and it's HIGH\n"); 
+				}
+				else {
+
+
+					p_ctx->hpd = (p_ctx->hpd  & 0x9F) | (CH7036HPD_HDVI_STATUS_CHANGED | CH7036HPD_HDVI_ATTACHED);
+					PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status changed since last query and it's HIGH\n");
+				}
+			}
+			else if (hpd ==0x80) {	
+				if( (p_ctx->hpd & CH7036HPD_HDVI_ATTACHED) ==0 )  {
+
+					p_ctx->hpd = (p_ctx->hpd  & 0x9F) & ((~ CH7036HPD_HDVI_STATUS_CHANGED) & (~CH7036HPD_HDVI_ATTACHED)) ;
+					PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status not changed since last query and it's LOW\n");
+				}
+				else {
+
+					p_ctx->hpd = (p_ctx->hpd  & 0x9F) | (CH7036HPD_HDVI_STATUS_CHANGED & (~CH7036HPD_HDVI_ATTACHED)) ;
+					PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status changed since last query and it's LOW\n");
+				}
+		
+			}
+			else if (hpd == 0x01) {
+
+				p_ctx->hpd = (p_ctx->hpd  & 0x9F) & ((~CH7036HPD_HDVI_STATUS_CHANGED) | CH7036HPD_HDVI_ATTACHED);
+				PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status has not changed since last query and it's HIGH\n");
+			}
+			else { 
+
+				p_ctx->hpd &= 0x9F; 
+				PD_DEBUG("ch7036_get_attached_device()- hdvi HPD status has not changed since last query and it's LOW\n");
+			}
+			
+
+			
+			PD_DEBUG("ch7036: ch7036_get_attached_device()- SUCCESS- hdmi hpd [0x%x]\n", hpd);
+			
+	}
+	else {
+
+		
+		if ( (!p_ctx->init_done) &&  (hpd == 0x86) )  {
+
+			p_ctx->hpd |= CH7036HPD_HDVI_ATTACHED;
+							
+		}
+
+		else {
+			p_ctx->hpd &= ~CH7036HPD_HDVI_ATTACHED;
+			
+		}
+		
+	}
+
+	if(status_crt == SS_SUCCESS) {  
+		
+		if( (p_ctx->hpd & CH7036HPD_CRT_ATTACHED )== CH7036HPD_CRT_ATTACHED)  
+			p_ctx->hpd = (p_ctx->hpd  & 0xF9) & ((~CH7036HPD_CRT_STATUS_CHANGED)  | CH7036HPD_CRT_ATTACHED);
+					
+		else 
+			p_ctx->hpd = ((p_ctx->hpd  & 0xF9) | ( CH7036HPD_CRT_STATUS_CHANGED | CH7036HPD_CRT_ATTACHED));
+									
+	} 
+	else  {  
+		
+		if( (p_ctx->hpd & CH7036HPD_CRT_ATTACHED ) == 0 ) { 
+			p_ctx->hpd &= 0xF9; 
+
+			if( (p_ctx->hpd & CH7036HPD_HDVI_ATTACHED)== 0  ) 
+				p_ctx->hpd |= 0x06; 
+										
+		}
+		else  {
+			
+			if ( (p_ctx->hpd & CH7036HPD_HDVI_ATTACHED) ==0 )
+				p_ctx->hpd &= 0xFB; 
+			else
+				p_ctx->hpd = (p_ctx->hpd & 0xF9) |  CH7036HPD_CRT_STATUS_CHANGED;		
+		}
+			
+	}
+
+	PD_DEBUG("ch7036_get_attached_device()- auto detection - exit- p_ctx->hpd= [0x%x]\n", p_ctx->hpd);	
+	return SS_SUCCESS;
+}
+
+
+void ch7036_reset(ch7036_device_context_t* p_ctx)
+{
+	DEV_CONTEXT* p_ch_ctx = p_ctx->p_ch7xxx_context;
+
+	ch7036_reset_mcu(p_ch_ctx); 
+	ch7036_reset_datapath(p_ch_ctx);
+
+	return;
+}
+
+void ch7036_reset_datapath(DEV_CONTEXT* p_ch_ctx)
+{
+
+	PD_DEBUG("ch7036: ch7036_reset_datapath()-enter\n");
+    I2CWrite(p_ch_ctx,0x03, 0x04); 
+	I2CWrite(p_ch_ctx,0x52, 0x2E);
+	
+	pd_usleep(50); 
+	I2CWrite(p_ch_ctx,0x52, 0x2F);
+	
+	return;
+}
+
+void ch7036_reset_mcu(DEV_CONTEXT* p_ch_ctx)
+{
+
+	PD_DEBUG("ch7036: ch7036_reset_mcu()-enter\n");
+
+    I2CWrite(p_ch_ctx,0x03, 0x04);
+	I2CWrite(p_ch_ctx,0x52, 0x2B);
+	
+	pd_usleep(50); 	
+	I2CWrite(p_ch_ctx,0x52, 0x2F);
+	
+	
+	PD_DEBUG("ch7036: ch7036_reset_mcu()-exit-\n");
+	return;
+}
+
+
+
+
+
+void ch7036_set_input_timing_info(ch7036_device_context_t *p_ctx, INPUT_INFO* pInput_Info)
+{
+	DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+	OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+
+	pd_timing_t * p_current_mode = &(p_ctx->native_dtd);
+	uint8 audio_id = AUDIO_SPDIF;
+	PD_DEBUG("ch7036_intf: ch7036_set_input_timing_info()-\n");
+
+	
+	if (p_ctx->init_done) { 
+
+	
+		pInput_Info->timing.ht = p_current_mode->htotal+1;
+	
+		pInput_Info->timing.ha = p_current_mode->width;
+		pInput_Info->timing.ho = p_current_mode->hsync_start - p_current_mode->hblank_start;
+		pInput_Info->timing.hw = p_current_mode->hsync_end - p_current_mode->hsync_start;
+		pInput_Info->timing.vt = p_current_mode->vtotal+1;
+	
+		pInput_Info->timing.va = p_current_mode->height;
+		pInput_Info->timing.vo = p_current_mode->vsync_start - p_current_mode->vblank_start;
+		pInput_Info->timing.vw = p_current_mode->vsync_end - p_current_mode->vsync_start;
+
+	
+		pInput_Info->rx_clk_khz = p_current_mode->dclk; 
+
+		
+		pInput_Info->hs_pol = ((uint8)(((p_current_mode)->mode_info_flags & PD_HSYNC_HIGH) >> 24 ))?1:0;  
+		pInput_Info->vs_pol = ((uint8)(((p_current_mode)->mode_info_flags & PD_VSYNC_HIGH) >> 24))?1:0; 
+
+	}
+
+
+	
+	
+	
+	pInput_Info->pixel_fmt = ((lvds_context_t *)p_ctx->internal_lvds)->panel_depth == 18?PIXEL_FMT_18BIT:3; 
+
+	
+	pInput_Info->data_ch_pol = POL_NO_INV;
+
+	
+	pInput_Info->data_ch_invert = POL_NO_INV;
+
+	
+
+	
+
+	pInput_Info->de_pol = POL_HIGH;  
+	
+	
+	
+	
+	
+	if(pOutput_Info->channel & CHANNEL_HDMI)
+		ch7036_set_audio_type(pInput_Info, audio_id);
+	
+}
+
+void ch7036_set_output_timing_info(ch7036_device_context_t *p_ctx, OUTPUT_INFO* pOutput_Info)
+{
+
+
+	PD_DEBUG("ch7036: ch7036_set_output_timing_info()\n");
+		
+	
+	PD_DEBUG("ch7036_set_output_timing_info()- output channel from pd context[%u]\n",pOutput_Info->channel);
+
+	
+	pOutput_Info->lvds_fmt.channel_swap = LVDS_CHANNEL_SWAP_DEF; 
+	pOutput_Info->lvds_fmt.channel_pol = (POL_LOW << 4) | (POL_LOW << 3) | (POL_LOW << 2) | (POL_LOW << 1) | (POL_LOW << 0);
+	pOutput_Info->lvds_fmt.pixel_fmt = p_ctx->dither_select;
+
+	
+	
+	pOutput_Info->hdmi_fmt.channel_swap = 0;
+	pOutput_Info->hdmi_fmt.data_pol_invert = POL_NO_INV;
+	pOutput_Info->hdmi_fmt.protect_enable = 0;
+
+
+	
+	
+	if (pOutput_Info->channel & CHANNEL_HDMI) 
+	{
+		
+		if(!(pOutput_Info->hdmi_fmt.is_dvi_mode))
+		{
+			PD_DEBUG("ch7036_set_output_timing_info- hdmi mode index is [0x%x]\n",p_ctx->hdmi_mode_index);
+			pOutput_Info->hdmi_fmt.format_index = (uint8)hdmi_timing_table[p_ctx->hdmi_mode_index].fmt_index; 
+			pOutput_Info->hdmi_fmt.aspect_ratio = (uint8)hdmi_timing_table[p_ctx->hdmi_mode_index].aspect;
+
+			pOutput_Info->timing.ht = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.ht;
+			pOutput_Info->timing.ha = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.ha;
+			pOutput_Info->timing.ho = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.ho;
+			pOutput_Info->timing.hw = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.hw;
+			pOutput_Info->timing.vt = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.vt;
+			pOutput_Info->timing.va = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.va;
+			pOutput_Info->timing.vo = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.vo;
+			pOutput_Info->timing.vw = hdmi_timing_table[p_ctx->hdmi_mode_index].timing.vw;
+			pOutput_Info->uclk_khz = hdmi_timing_table[p_ctx->hdmi_mode_index].clk_freq;
+		}
+		else 
+		{
+			pOutput_Info->hdmi_fmt.format_index = (uint8)dvi_timing_table[p_ctx->dvi_mode_index].fmt_index; 
+			pOutput_Info->hdmi_fmt.aspect_ratio = (uint8)dvi_timing_table[p_ctx->dvi_mode_index].aspect;
+
+			pOutput_Info->timing.ht = dvi_timing_table[p_ctx->dvi_mode_index].timing.ht;
+			pOutput_Info->timing.ha = dvi_timing_table[p_ctx->dvi_mode_index].timing.ha;
+			pOutput_Info->timing.ho = dvi_timing_table[p_ctx->dvi_mode_index].timing.ho;
+			pOutput_Info->timing.hw = dvi_timing_table[p_ctx->dvi_mode_index].timing.hw;
+			pOutput_Info->timing.vt = dvi_timing_table[p_ctx->dvi_mode_index].timing.vt;
+			pOutput_Info->timing.va = dvi_timing_table[p_ctx->dvi_mode_index].timing.va;
+			pOutput_Info->timing.vo = dvi_timing_table[p_ctx->dvi_mode_index].timing.vo;
+			pOutput_Info->timing.vw = dvi_timing_table[p_ctx->dvi_mode_index].timing.vw;
+			pOutput_Info->uclk_khz = dvi_timing_table[p_ctx->dvi_mode_index].clk_freq;
+
+		}
+
+
+
+	} else if((pOutput_Info->channel & CHANNEL_VGA) && ((pOutput_Info->channel & CHANNEL_HDMI)==0x00) ) 
+	{
+		
+		
+		
+		PD_DEBUG("ch7036_set_output_timing_info- crt mode index is [0x%x]\n",p_ctx->crt_mode_index);
+		pOutput_Info->timing.ht = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.ht;
+		pOutput_Info->timing.ha = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.ha;
+		pOutput_Info->timing.ho = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.ho;
+		pOutput_Info->timing.hw = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.hw;
+		pOutput_Info->timing.vt = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.vt;
+		pOutput_Info->timing.va = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.va;
+		pOutput_Info->timing.vo = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.vo;
+		pOutput_Info->timing.vw = ch7036_crt_timing_table[p_ctx->crt_mode_index].timing.vw;
+		pOutput_Info->uclk_khz = ch7036_crt_timing_table[p_ctx->crt_mode_index].clk_freq;
+
+		
+	} else
+		; 
+
+	
+	if(pOutput_Info->channel & CHANNEL_HDMI)
+		ch7036_set_hdmi_sync_polarity(pOutput_Info);
+
+	if(pOutput_Info->channel & CHANNEL_HDMI || pOutput_Info->channel & CHANNEL_VGA) {
+		
+		ch7036_set_rotate (pOutput_Info);
+		ch7036_set_hflip (pOutput_Info);
+		ch7036_set_vflip (pOutput_Info);
+	}
+}
+
+void ch7036_set_prefer_timing_info(ch7036_device_context_t *p_ctx, PREFER_INFO* pPrefer_Info)
+{
+	
+	
+	
+
+	PD_DEBUG("ch7036_intf: ch7036_set_prefer_timing_info()\n");
+
+	
+	if (!p_ctx->init_done) {
+
+	pPrefer_Info->mclk_khz = 166000; 
+	pPrefer_Info->uclkod_sel = 1;
+	pPrefer_Info->dat16_32b = 0;
+	pPrefer_Info->true24 = 0;
+	pPrefer_Info->true_com = 0;
+	pPrefer_Info->lvds_out_hs_tolerance = HS_TOLERANCE_LEVEL0;
+	pPrefer_Info->lvds_out_reset_bit_sel = RST_BIT_VSYNC;
+	pPrefer_Info->dither_filter_enable = DITHER_ENABLE;  
+		
+	pPrefer_Info->hscale_ratio_gate = 130;	
+	pPrefer_Info->reset=0; 
+	pPrefer_Info->vga_enable=0;
+
+	pPrefer_Info->text_enhancement = DEFAULT_TEXT_ENHANCE; 
+	pPrefer_Info->pll_ref_dly = DEF_PLL_REF_DLY;
+	pPrefer_Info->pll_ref_fbdly = DEF_PLL_REF_FBDLY;
+	pPrefer_Info->lvds_txdrv_ctrl = DEF_LVDS_TXDRV_CTRL;
+
+	pPrefer_Info->eye_bgtrim=0;
+	pPrefer_Info->eye_dacg=0;
+	pPrefer_Info->eye_dri_demp=0;
+	pPrefer_Info->eye_dri_pll_cp=0;
+	pPrefer_Info->eye_dri_damp=0;
+	pPrefer_Info->eye_dri_pll_rlf=0;
+	pPrefer_Info->eye_rdac=0;
+
+	}
+
+	pPrefer_Info->scale_line_adjust = 0;
+
+
+	
+}
+
+
+ch7036_status_t ch7036_parse_standard_edid(ch7036_device_context_t* p_ctx, uint32 channel)
+{
+	uint8 i, index = 0;
+	
+	ch7036_edid_blk_t* p_edid = (ch7036_edid_blk_t *)p_ctx->cedid;
+	unsigned char* p_edidblk = p_edid->edidblk;
+
+	
+	OUT_FMT* p_table = ch7036_crt_timing_table;
+	TIMING* p_timing;
+
+	unsigned char j=0;
+
+
+
+
+	
+	established_timings_t *p_etiming_I = p_edid->etiming_I;
+	established_timings_t *p_etiming_II = p_edid->etiming_II;
+
+
+	
+	standard_timings_t	*stiming = p_edid->stiming; 
+	ch7036_attr_table_index_t* p_modes =  p_edid->modes;
+
+	unsigned long idx = 2; 
+
+
+	PD_DEBUG("ch7036_parse_stardard_edid() channel [0x%x] - enter...\n", channel);
+
+
+	if(channel == CHANNEL_LVDS_HDMI) {
+
+		p_edid = (ch7036_edid_blk_t *)p_ctx->hedid;
+		p_edidblk = p_edid->edidblk;
+		p_etiming_I = p_edid->etiming_I;
+		p_etiming_II = p_edid->etiming_II;
+
+		stiming = p_edid->stiming; 
+		p_modes =  p_edid->modes;
+
+		
+		if (p_edid->ebn > 1) { 
+			idx = 1;
+			p_table = hdmi_timing_table;
+		}
+		else { 
+			idx = 0;
+			p_table = dvi_timing_table;
+			channel = 7; 
+		}
+
+
+	}
+
+	
+	while (index < MAX_ATTR_LIST_SIZE)
+		p_modes[index++] = FALSE; 
+
+
+	if (p_edidblk[EDID_EXTENSION_FLAG] == 0x00 ) {
+			
+
+		ch7036_parse_standard_timing(p_edid,0);
+
+		
+		ch7036_parse_established_timing(p_ctx, p_edid);
+		
+
+		
+		ch7036_parse_detailed_descriptor_blocks(p_ctx, p_edid);
+				
+
+		
+		for(i=0; i<8;i++) { 
+
+
+			index=0;
+			while (index < MAX_ATTR_LIST_SIZE ) {
+				if(p_modes[index]== TRUE) {
+					index++; 
+					continue;
+				}
+				p_timing = &(p_table[index].timing);
+
+				if ( (p_edid->dtblk[j]).data_tag & 0x00FFFFFF ) { 
+					OUT_FMT* p_dtd = &((p_edid->dtblk[j]).dtiming);
+					
+					if( (p_dtd->timing.ha == p_timing->ha) && (p_dtd->timing.va == p_timing->va) && (p_dtd->timing.hz >= p_timing->hz) ) {
+						p_modes[index] = TRUE;
+						j= j> 3?3:j+1;
+
+						PD_DEBUG("ch7036_parse_standard_edid()- detailed timing mode supported- index [%d] name [%s]...\n",index,ch7036_get_mode_name(channel,index) );
+
+					}
+
+				}
+							
+				
+				if( (stiming[i].ha == p_timing->ha) && (stiming[i].va == p_timing->va) && (stiming[i].refresh_rate >= p_timing->hz) ) {
+					p_modes[index] = TRUE;
+					PD_DEBUG("ch7036_parse_standard_edid()- std_timing mode supported- index [%d] name [%s]...\n",index,ch7036_get_mode_name(channel,index) );
+				}
+				
+				index++;
+
+			}
+
+		}
+
+		
+		for(i=0;i<4;i++) {
+			if ( (p_edid->dtblk[i]).data_tag == 0xFA000000) {
+				; 
+				continue;
+			}
+		}
+
+		
+
+		for(i=0; i<8;i++) { 
+
+			
+			
+			if( (p_etiming_I[i].is_supported == TRUE) && (p_etiming_I[i].index[idx] != OUT_CRT_END) ) {
+				p_modes[p_etiming_I[i].index[idx]] = TRUE; 
+				PD_DEBUG("ch7036_parse_standard_edid()- et1 mode supported- index [%d] name [%s]...\n",p_etiming_I[i].index[idx],p_etiming_I[i].mode_name);
+				continue;
+
+			}
+
+			
+			if( (i==7) && (channel ==7) && (p_etiming_I[i].is_supported == TRUE) ) {
+				p_modes[p_etiming_I[i].index[idx]] = TRUE; 
+				PD_DEBUG("ch7036_parse_standard_edid()- et1 mode supported- index [%d] name [%s]...\n",p_etiming_I[i].index[idx],p_etiming_I[i].mode_name);
+			}
+
+			
+		}
+
+		for(i=0; i<8;i++) { 
+		
+			if( (p_etiming_II[i].is_supported == TRUE) && (p_etiming_II[i].index[idx] != OUT_CRT_END) ) {
+				p_modes[p_etiming_II[i].index[idx]] = TRUE; 
+				PD_DEBUG("ch7036_parse_standard_edid()- et2 mode supported- index [%d] name [%s]...\n",p_etiming_II[i].index[idx],p_etiming_II[i].mode_name);
+				continue;
+
+			}
+
+		}
+
+		
+
+	}
+	else { 
+		PD_DEBUG("ch7036_parse_standard_edid()- vga/dvi has more than one 128 byte block\n");
+	}
+
+
+	PD_DEBUG("ch7036_parse_stardard_edid()-channel [0x%x] - exit...\n", channel);
+
+	return SS_SUCCESS;
+
+}
+
+void ch7036_parse_detailed_descriptor_blocks(ch7036_device_context_t* p_ctx, ch7036_edid_blk_t* p_edid)
+{
+	unsigned long *monitor_descriptor;
+	unsigned char* p_ebuf, *p_st;
+	unsigned char* p_edidblk = p_edid->edidblk;
+	unsigned char i;
+	OUT_FMT* p_dt;
+	
+
+	p_ebuf = &(p_edidblk[EDID_DETAILED_TIMING_DESCRIPTION_1]);
+
+	PD_DEBUG("parse_detailed_descriptor_blocks()- enter...\n");
+
+	for(i=0;i<4;i++) {
+
+		monitor_descriptor = (unsigned long *) p_ebuf;
+
+		if((*monitor_descriptor) & 0x00FFFFFF ) { 
+			
+			
+			p_dt = &(p_edid->dtblk[i].dtiming);				
+			ch7036_parse_detailed_timing(p_dt, p_ebuf);
+			
+		}
+			
+		else { 
+
+			p_st = p_ebuf;
+			p_st +=5;
+
+			switch (*monitor_descriptor) {
+				case 0xFA000000: 
+					ch7036_parse_standard_timing(p_edid,p_st); 
+					break;
+
+				case 0xFD000000: 
+					(p_edid->rtiming).vrate_min = *p_st; 
+					(p_edid->rtiming).vrate_max = *(p_st+1);
+					(p_edid->rtiming).hrate_min = *(p_st+2); 
+					(p_edid->rtiming).hrate_max = *(p_st+3); 
+					(p_edid->rtiming).pclk_max = (unsigned long)(*(p_st+4))*10000L;	
+					
+					
+					break;
+
+				case 0xFC000000: 
+				case 0xFF000000: 
+				default: 
+					break;
+			}
+		}
+
+		(p_edid->dtblk[i]).data_tag = *monitor_descriptor;
+
+		p_ebuf += 18;
+	}
+	
+	return;
+}
+
+void ch7036_parse_detailed_timing(OUT_FMT *p_dt, unsigned char* p_ebuf)
+{
+
+	unsigned short blanking;
+
+	PD_DEBUG("ch7036_parse_detailed_descriptor_timing()- enter...\n");
+
+
+	p_dt->clk_freq = ((uint32)(p_ebuf[1]<<8) | p_ebuf[0]) * 10; 
+
+	p_dt->timing.ha = ((uint16)(p_ebuf[4] & 0xF0) << 4) | p_ebuf[2];
+
+	PD_DEBUG("ch7036_parse_detailed_timing() byte 3 [%x] byte 5 [%x]\n",p_ebuf[2],p_ebuf[4]);
+
+	blanking = ((uint16)(p_ebuf[4] & 0x0F) << 8) | p_ebuf[3]; 
+	p_dt->timing.ht = p_dt->timing.ha + blanking;
+
+	p_dt->timing.va = ((uint16)(p_ebuf[7] & 0xF0) << 4) | p_ebuf[5];
+
+	PD_DEBUG("ch7036_parse_detailed_timing() byte 6 [%x] byte 8 [%x]\n",p_ebuf[5],p_ebuf[7]);
+
+	blanking = ((uint16)(p_ebuf[7] & 0x0F) << 8) | p_ebuf[6]; 
+	p_dt->timing.vt = p_dt->timing.va + blanking;
+
+	PD_DEBUG("ch7036_parse_detailed_timing()- pclk [%d] Khz ha [%d] va [%d] ht [%d] vt [%d]\n",p_dt->clk_freq,p_dt->timing.ha,p_dt->timing.va,p_dt->timing.ht,p_dt->timing.vt);
+
+	p_dt->timing.hz = 	(((p_dt->clk_freq / p_dt->timing.ht) + 1 ) * 1000) / p_dt->timing.vt; 
+
+	p_dt->timing.stype = (p_ebuf[17] & 0x80)?0:1; 
+
+	PD_DEBUG("ch7036_parse_detailed_timing()- refresh [%d] scantype [%d]\n",
+		p_dt->timing.hz,p_dt->timing.stype);
+
+	return;	
+}
+
+
+
+void ch7036_parse_standard_timing(ch7036_edid_blk_t* p_edid, unsigned char* p_addtional_st)
+{
+	standard_timings_t *stiming = p_edid->stiming;
+	unsigned char i, max=8;
+
+	unsigned char* p_edidblk = &(p_edid->edidblk[EDID_STANDARD_TIMINGS]);
+
+	
+	PD_DEBUG("ch7036_parse_standard_timing()- enter\n");
+	
+	if(p_addtional_st) {
+		p_edidblk = p_addtional_st;
+		stiming = p_edid->stiming_x;
+		max = 6;
+	}
+
+	for(i = 0; i < max; stiming++,i++) {
+			
+	
+		if( (*p_edidblk) == 0x01 &&  *(p_edidblk+1) == 0x01) 
+			continue;
+	
+		stiming->ha = ((*p_edidblk) + 31) << 3 ;
+		 
+		stiming->refresh_rate = (*(p_edidblk + 1) & 0x3F) + 60;
+
+		switch(*(p_edidblk +1) >> 6) {
+	
+		   case 0: 
+			   stiming->va =  (stiming->ha *10) >> 4;
+			   break;
+		   case 1: 
+			   stiming->va =  (stiming->ha *3) >> 2;
+			   break;
+		   case 2: 
+			   stiming->va =  (stiming->ha << 2) / 5;			       
+			   break;
+		   case 3: 
+			   stiming->va =  (stiming->ha* 9) >>4;			       
+			   break;
+		   default:
+			   break;
+		} 
+
+		p_edidblk +=2;
+
+		PD_DEBUG("ch7036_parse_standard_timing()- ha [%d] va [%d] refresh [%d]\n",stiming->ha,stiming->va,stiming->refresh_rate);
+
+	} 
+	
+	return;
+}
+
+
+
+
+void ch7036_parse_established_timing(ch7036_device_context_t* p_ctx, ch7036_edid_blk_t* p_edid) 
+{
+
+	unsigned char* p_edidblk = p_edid->edidblk;
+
+	
+
+	established_timings_t *p_etiming_I = p_edid->etiming_I;
+	established_timings_t *p_etiming_II = p_edid->etiming_II;
+	established_timings_t *p_etiming_man = p_edid->etiming_man;
+
+	unsigned char i=0;
+	unsigned char et1, et2;
+
+	PD_DEBUG("ch7036_parse_established_timing()- enter...\n");
+
+	et1 = p_edidblk[EDID_ESTABLISHED_TIMINGS_1];
+	et2 = p_edidblk[EDID_ESTABLISHED_TIMINGS_2];
+
+
+
+	for(i=0; i<8;i++) {
+	  p_etiming_I[i].is_supported = FALSE;
+	  p_etiming_II[i].is_supported = FALSE;
+	}
+
+
+
+	p_etiming_man->is_supported = FALSE;
+ 
+
+	for(i=0;i<8;i++) {
+
+
+		
+		if(et1 & 0x01) {   
+			p_etiming_I[i].is_supported = TRUE;
+	
+		}
+		
+		
+		if(et2 & 0x01) {   
+			p_etiming_II[i].is_supported = TRUE;
+	
+		}
+
+		et1 >>=  1;
+		et2 >>=  1;
+
+	}
+
+
+	
+	if (p_edidblk[EDID_MANUFACTURERS_RESERVED_TIMINGS] & 0x80) {
+
+		p_etiming_man->is_supported = TRUE;
+	 
+	}
+
+
+	return;
+
+}
+
+
+ch7036_status_t ch7036_parse_cea_edid(ch7036_device_context_t* p_ctx)
+{
+	uint8 tag, blk_size =0; 
+	uint8 index = 0;
+	
+	uint16 count;
+
+	uint8*  p_buff;
+
+
+	ch7036_edid_blk_t* p_hedid = (ch7036_edid_blk_t *)p_ctx->hedid;
+
+	unsigned char* p_edidblk = p_hedid->edidblk;
+	ch7036_attr_table_index_t* p_modes =  p_hedid->modes;
+
+	
+	PD_DEBUG("ch7036_parse_cea_edid()- enter...\n");
+
+	while (index < MAX_ATTR_LIST_SIZE )
+		p_modes[index++] = FALSE; 
+	
+		
+	if(p_edidblk[EDID_CEA_DETAILED_TIMING_DATA_OFFSET] == 0 ||  p_edidblk[EDID_CEA_DETAILED_TIMING_DATA_OFFSET] > 124) {
+		PD_DEBUG("ch7036_parse_cea_edid()- invalid data block size [%d]\n", p_edidblk[EDID_CEA_DETAILED_TIMING_DATA_OFFSET]);
+		return SS_UNSUCCESSFUL;
+	}
+
+	
+
+	PD_DEBUG("ch7036_parse_cea_edid()- CEA revision [0x%x]...\n",p_edidblk[EDID_CEA_REVISION]);
+	
+	if(p_edidblk[EDID_CEA_TAG] == 0x02 && p_edidblk[EDID_CEA_REVISION] == 0x03)
+	{
+		
+		p_buff = &(p_edidblk[EDID_CEA_DATA_BLOCK]);
+
+		
+
+		count=4 ; 
+		for(; count < p_edidblk[EDID_CEA_DETAILED_TIMING_DATA_OFFSET]; p_buff += blk_size) {
+
+			blk_size = (*p_buff) & 0x1F; 
+			tag = (*p_buff) & 0xE0; 
+
+			PD_DEBUG("ch7036_parse_cea_edid()- data type [0x%x] block_size [%d]\n", tag, blk_size);
+
+			p_buff++;
+			switch (tag) { 
+			
+				case 0x20: 
+				
+					break;
+
+				case 0x40: 
+					ch7036_parse_cea_video_data_block(blk_size, p_buff, p_hedid);
+					break;
+
+				case 0x60: 
+					break;
+
+				case 0x80: 
+					break;
+
+				default:
+					break;
+
+			}
+
+			count += (blk_size + 1); 
+					
+
+		} 
+	
+	} 
+	
+
+	PD_DEBUG("ch7036_parse_cea_edid()- exit...\n");
+
+	return SS_SUCCESS;
+
+	
+}
+
+
+void ch7036_parse_cea_video_data_block(uint8 blk_size, uint8* p_buff, ch7036_edid_blk_t* p_edid)
+{
+	uint8 i, index;
+
+	ch7036_attr_table_index_t* p_modes =  p_edid->modes;
+
+	for(i=1; i <= blk_size; i++, p_buff++ ) {
+		
+			index=0;
+
+			PD_DEBUG("ch7036_parse_cea_video_data_block()- HDMI display video code [0x%x]\n",(*p_buff) & 0x7F);
+			
+			while (index < OUT_HDMI_END) { 
+			
+				
+				if( p_modes[index] == TRUE  ) {
+					index++;
+					continue;
+				}
+				
+
+				if( ((*p_buff) & 0x7F) == hdmi_timing_table[index].fmt_index  ) {				
+					
+					p_modes[index] = TRUE;
+					PD_DEBUG("ch7036_parse_cea_video_data_block()- mode supported: global table index [%d] name [%s]...\n",index, ch7036_get_mode_name(CHANNEL_LVDS_HDMI,index) );
+					
+					if( hdmi_timing_table[index-1].fmt_index == hdmi_timing_table[index].fmt_index) {						 
+		
+						break; 
+					}
+
+				}  
+				
+				index++;
+								   
+			} 
+	} 
+
+	return;
+}
+
+
+ch7036_status_t ch7036_parse_edid(ch7036_device_context_t* p_ctx)
+{
+
+
+	DEV_CONTEXT* p_ch7xxx_context = p_ctx->p_ch7xxx_context;
+	OUTPUT_INFO* pOutput_Info = p_ch7xxx_context->pOutput_Info;
+
+	ch7036_edid_blk_t* p_hedid = (ch7036_edid_blk_t *)p_ctx->hedid;
+	ch7036_edid_blk_t* p_cedid = (ch7036_edid_blk_t *)p_ctx->cedid;
+
+	unsigned char* p_edidblk=0; 
+	ch7036_attr_table_index_t* p_modes = 0;
+	pd_attr_t  *p_attr = NULL ;
+	int RESET =1;
+
+	PD_DEBUG("ch7036_parse_edid()- enter...\n");
+
+	
+	//hpd checking schemes
+	if(p_ctx->hpd == 0) 
+		return SS_SUCCESS;
+
+
+	if ( 
+		( (pOutput_Info->channel & 0x02) &&  (p_ctx->hpd & 0x80) )||
+		( (pOutput_Info->channel & 0x04) &&  (p_ctx->hpd & 0x08) )
+		)
+		//parsing is already done
+		return SS_SUCCESS;
+
+	
+	switch (pOutput_Info->channel) {
+		case CHANNEL_LVDS_HDMI:
+		case CHANNEL_HDMI:
+			if(p_hedid->is_edid) { 
+				p_edidblk = p_hedid->edidblk;	
+
+				p_hedid->is_preferred_timing = (p_edidblk[EDID_FEATURE_SUPPORT] >> 1) & 0x1;
+
+				
+				if(pOutput_Info->hdmi_fmt.is_dvi_mode == 0) {
+					p_attr = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs, PD_ATTR_ID_HDMI_OUT_MODE, 0);
+					ch7036_parse_cea_edid(p_ctx);
+				}
+				else {
+					p_attr = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs, PD_ATTR_ID_DVI_OUT_MODE, 0);
+					ch7036_parse_standard_edid(p_ctx, CHANNEL_LVDS_HDMI);
+				}
+
+								
+				
+				p_ctx->hpd |= 0x80; //don't parse again next time
+							
+			}
+			else { 
+
+				PD_DEBUG("ch7036_parse_edid()- hdmi edid read failed or never done...use default...\n");
+				ch7036_set_edid_display_supported_attr( (void *)p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,p_ctx->downscaled,p_hedid->modes,RESET);
+				p_ctx->hpd &= 0x7F; //allow to enter parsing block again
+
+			}
+
+			p_modes = p_hedid->modes;
+			
+			break;
+
+		case CHANNEL_LVDS_VGA:
+		case CHANNEL_VGA:
+			if(p_cedid->is_edid) { 
+				p_edidblk = p_cedid->edidblk;
+
+				p_cedid->is_preferred_timing = (p_edidblk[EDID_FEATURE_SUPPORT] >> 1) & 0x1;
+				p_attr = pd_get_attr(p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs, PD_ATTR_ID_CRT_OUT_MODE, 0);
+								
+				ch7036_parse_standard_edid(p_ctx, CHANNEL_LVDS_VGA);
+				p_ctx->hpd |= 0x08;
+			}
+			else {
+				PD_DEBUG("ch7036_parse_edid()- vga edid read failed or never done...use default...\n");
+				ch7036_set_edid_display_supported_attr( (void *)p_ctx->p_ch7036_attr_table, p_ctx->ch7036_num_attrs,p_ctx->downscaled,p_cedid->modes,RESET);
+				p_ctx->hpd &= 0x7F; //allow to enter parsing block again
+			}
+			p_modes = p_cedid->modes;
+			
+			break;
+		default:
+			//there is no separate DVI display channel, or LVDS edid reading at this time
+			//DVI display option should already be mapped to HDMI channel
+			p_edidblk = 0;
+
+	}
+
+	if(p_edidblk) {
+
+		ch7036_set_edid_display_supported_attr( (void *)p_attr,0,p_ctx->downscaled,p_modes,0);
+
+	}
+
+	PD_DEBUG("ch7036_parse_edid()- exit...\n");
+
+	return SS_SUCCESS;
+}
+
+
+void ch7036_alter_display_table(int all, void *p_table,unsigned char* p_modes, void* val,unsigned long* p_invis,unsigned char is_invis,unsigned char is_6x4)
+{
+	pd_attr_t  *p_attr;
+	unsigned long i,j;
+	
+
+	PD_DEBUG("ch7036_alter_display_table()-enter...\n");
+
+	if(all) { 
+		unsigned long* num_attrs = (unsigned long *)val;
+		for(i=0;i<3;i++) { //all 3 tables: hdmi, dvi, vga
+			
+			p_attr = pd_get_attr((pd_attr_t *)p_table, *num_attrs, PD_ATTR_ID_HDMI_OUT_MODE+i, 0);
+			if(is_6x4) 
+				p_attr++;  		
+			else 
+				p_attr= p_attr + ch7036_invis_6x4_modes_table_size[i] + 1; //1 is to skip header
+
+					
+			for(j=0; j < *p_invis;j++) { 
+				if(is_invis)
+					p_attr->flags  |= PD_ATTR_FLAG_USER_INVISIBLE;  
+				else 
+					p_attr->flags  &= ~PD_ATTR_FLAG_USER_INVISIBLE; 
+
+
+				p_attr++;
+			}
+			p_invis++; //now, grab dvi, then vga table size
+			
+
+		}
+
+	}
+	else { 
+		unsigned long id= 0,k;
+		p_attr = (pd_attr_t *)p_table;
+		id = p_attr->id;
+
+		if(is_6x4) {
+			p_attr++;  
+			j=0;
+		}
+		else {
+			p_attr= p_attr + ch7036_invis_6x4_modes_table_size[id - PD_ATTR_ID_HDMI_OUT_MODE] + 1; //point to the first 7x4 entry			
+			j= ch7036_invis_6x4_modes_table_size[id - PD_ATTR_ID_HDMI_OUT_MODE];
+		}
+		p_invis = p_invis + (id - PD_ATTR_ID_HDMI_OUT_MODE);
+		k= *p_invis + j;
+
+		for(; j < k;j++) { 
+			if(is_invis) {
+				p_attr->flags  |= PD_ATTR_FLAG_USER_INVISIBLE;  
+				p_modes[j]=FALSE;
+			} 
+	
+			p_attr++;
+		}
+			
+	}
+}
+
+
+ch7036_status_t ch7036_set_edid_display_supported_attr(void *p_table, unsigned long num_attrs, unsigned char* p_downscaled, unsigned char* p_modes, int is_reset)
+{
+
+	pd_list_attr_t *p_hdr = (pd_list_attr_t *)p_table;
+	pd_attr_t *p_entry = (pd_attr_t *)p_table; 
+	
+	uint8 i=0;
+
+#ifdef T_SHOW_EDID_DISPLAY_ATTR
+	pd_list_entry_attr_t *list_entry;
+#endif
+	
+	PD_DEBUG("ch7036_set_edid_display_supported_attr()-enter... is_reset status = [%d]\n", is_reset);
+
+	if(is_reset) {
+		while (i < MAX_ATTR_LIST_SIZE ) {
+			p_modes[i++] = TRUE; 
+		}
+
+		
+		
+		//special handling for 1080i/p @ 59Hz
+		p_entry = pd_get_attr((pd_attr_t *)p_table, num_attrs, PD_ATTR_ID_HDMI_OUT_MODE, 0);
+		p_entry++;
+		p_entry = p_entry + OUT_HDMI_1920x1080I_59;
+		p_entry->flags  |= PD_ATTR_FLAG_USER_INVISIBLE;  
+		p_entry += 2;
+		p_entry->flags  |= PD_ATTR_FLAG_USER_INVISIBLE;  
+
+	}
+	else { 
+
+		PD_DEBUG("ch7036_set_edid_display_supported_attr()-start to build edid display mode list...\n");
+	
+		p_entry++; 
+
+		for (i = 0; i < p_hdr->num_entries ; ++i,++p_entry) { 
+			if( 
+				(p_modes[i] == FALSE) ||
+				//1080 i/p @ 59 Hz
+				((p_hdr->id == PD_ATTR_ID_HDMI_OUT_MODE) && (i == OUT_HDMI_1920x1080I_59 || i== OUT_HDMI_1920x1080P_59) ) ){
+
+				p_entry->flags  |= PD_ATTR_FLAG_USER_INVISIBLE;  
+				continue;
+			}
+		
+
+			p_entry->flags  &= ~PD_ATTR_FLAG_USER_INVISIBLE; 
+
+		}
+
+
+	}
+	
+	//special handling for 8x6,7x4,6x4- 
+	ch7036_alter_display_table(is_reset,p_table,p_modes,(void *)&num_attrs,ch7036_invis_6x4_modes_table_size,*p_downscaled,1);			
+	p_downscaled++;
+	ch7036_alter_display_table(is_reset,p_table,p_modes,(void *)&num_attrs,ch7036_invis_8x6_7x4_table_size,*p_downscaled,0);
+
+#ifdef T_SHOW_EDID_DISPLAY_ATTR
+
+	list_entry = (pd_list_entry_attr_t *)(p_table);
+
+	for (i = 0,++list_entry; i < p_hdr->num_entries; ++i, ++list_entry) 
+		PD_DEBUG("ch7036 : ch7036_set_edid_display_supported_attr : \n"
+				  "list entry[%hhu]=%s, id=%lu, "
+					  "value=%lu, flags=0x%x \n",
+					  i, list_entry->name, list_entry->id,
+					  list_entry->value, (unsigned char)list_entry->flags);
+#endif
+
+
+	return SS_SUCCESS;
+}
+
+
+uint8 * ch7036_get_mode_name(uint32 channel, uint8 index)
+{
+	uint8* str = "Name String Is Not Yet Converted";
+
+	switch (channel) {
+
+		case CHANNEL_LVDS_HDMI:
+			switch (index) {
+				case OUT_HDMI_640x480P_59:
+					return ("OUT_HDMI_640x480P_59");					
+				case OUT_HDMI_640x480P_60:
+					return ("OUT_HDMI_640x480P_60");
+				case OUT_HDMI_720x480P_59:
+					return ("OUT_HDMI_720x480P_59");
+				case OUT_HDMI_720x480P_60:
+					return ("OUT_HDMI_720x480P_60");
+				case OUT_HDMI_1280x720P_59:
+					return ("OUT_HDMI_1280x720P_59");					
+				case OUT_HDMI_1280x720P_60:
+					return ("OUT_HDMI_1280x720P_60");
+				case OUT_HDMI_1920x1080I_59:
+					return ("OUT_HDMI_1920x1080I_59");					
+				case OUT_HDMI_1920x1080I_60:
+					return ("OUT_HDMI_1920x1080I_60");
+				case OUT_HDMI_1920x1080P_59:
+					return ("OUT_HDMI_1920x1080P_59");
+				case OUT_HDMI_1920x1080P_60:
+					return ("OUT_HDMI_1920x1080P_60");
+				
+
+			}
+			break;
+
+		case CHANNEL_LVDS_VGA:
+
+			switch (index) {
+
+				case OUT_CRT_640x400_85:
+					return ("OUT_CRT_640x400_85");
+
+				case OUT_CRT_640x480_60:
+					return ("OUT_CRT_640x480_60");
+				case OUT_CRT_640x480_72:
+					return ("OUT_CRT_640x480_72");
+				case OUT_CRT_640x480_75:
+					return ("OUT_CRT_640x480_75");
+				case OUT_CRT_640x480_85:
+					return ("OUT_CRT_640x480_85");
+
+				case OUT_CRT_720x400_85:
+					return ("OUT_CRT_720x400_85");
+
+				case OUT_CRT_800x600_56:
+					return ("OUT_CRT_800x600_56");
+				case OUT_CRT_800x600_60:
+					return ("OUT_CRT_800x600_60");
+				case OUT_CRT_800x600_72:
+					return ("OUT_CRT_800x600_72");
+				case OUT_CRT_800x600_75:
+					return ("OUT_CRT_800x600_75");
+					
+				case OUT_CRT_800x600_85:
+					return ("OUT_CRT_800x600_85");
+
+				case OUT_CRT_1024x768_60:
+					return ("OUT_CRT_1024x768_60");
+				case OUT_CRT_1024x768_70:
+					return ("OUT_CRT_1024x768_70");
+				case OUT_CRT_1024x768_75:
+					return ("OUT_CRT_1024x768_75");
+				case OUT_CRT_1024x768_85:
+					return ("OUT_CRT_1024x768_85");
+
+				case OUT_CRT_1152x864_75:
+					return ("OUT_CRT_1152x864_75");
+
+				case OUT_CRT_1280x768_60:
+					return ("OUT_CRT_1280x768_60");
+				case OUT_CRT_1280x768_75:
+					return ("OUT_CRT_1280x768_75");
+				case OUT_CRT_1280x768_85:
+					return ("OUT_CRT_1280x768_85");
+
+				case OUT_CRT_1280x960_60:
+					return ("OUT_CRT_1280x960_60");
+				case OUT_CRT_1280x960_85:
+					return ("OUT_CRT_1280x960_85");	
+					
+				case OUT_CRT_1280x1024_60:
+					return ("OUT_CRT_1280x1024_60");
+				case OUT_CRT_1280x1024_75:
+					return ("OUT_CRT_1280x1024_75");
+				case OUT_CRT_1280x1024_85:
+					return ("OUT_CRT_1280x1024_85");
+
+				case OUT_CRT_1360x768_60:
+					return ("OUT_CRT_1360x768_60");
+
+				case OUT_CRT_1400x1050_60:
+					return ("OUT_CRT_1400x1050_60");
+				case OUT_CRT_1400x1050_75:
+					return ("OUT_CRT_1400x1050_75");
+
+				case OUT_CRT_1440x900_60:
+					return ("OUT_CRT_1440x900_60");
+
+				case OUT_CRT_1440x1050_60:
+					return ("OUT_CRT_1440x1050_60");
+
+				case OUT_CRT_1600x900_60:
+					return ("OUT_CRT_1600x900_60");
+
+				case OUT_CRT_1600x1200_60:
+					return ("OUT_CRT_1600x1200_60");	
+					
+				case OUT_CRT_1920x1080_60:
+					return ("OUT_CRT_1920x1080_60");
+
+			}
+			break;
+
+		default: 
+			switch (index) {
+				case OUT_DVI_640x480_60:
+					return ("OUT_DVI_640x480_60"); 
+				case OUT_DVI_640x480_72:
+					return ("OUT_DVI_640x480_72"); 
+
+				case OUT_DVI_720x400_70:
+					return ("OUT_DVI_720x400_70"); 
+
+				case OUT_DVI_800x600_56:
+					return ("OUT_DVI_800x600_56");
+				case OUT_DVI_800x600_60:
+					return ("OUT_DVI_800x600_60"); 
+				case OUT_DVI_800x600_72:
+					return ("OUT_DVI_800x600_72");
+				case OUT_DVI_800x600_75:
+					return ("OUT_DVI_800x600_75");
+
+				case OUT_DVI_1024x768_60:
+					return ("OUT_DVI_1024x768_60");
+				case OUT_DVI_1024x768_70:
+					return ("OUT_DVI_1024x768_70");
+				case OUT_DVI_1024x768_75:
+					return ("OUT_DVI_1024x768_75");
+
+				case OUT_DVI_1152x864_60:
+					return ("OUT_CRT_1152x864_60");
+
+				case OUT_DVI_1280x720_60:
+					return ("OUT_DVI_1280x720_60");
+
+				case OUT_DVI_1280x800_60:
+					return ("OUT_DVI_1280x800_60");
+
+				case OUT_DVI_1280x960_60:
+					return ("OUT_DVI_1280x960_60");
+
+				case OUT_DVI_1280x1024_60:
+					return ("OUT_DVI_1280x1024_60");
+				case OUT_DVI_1280x1024_75:
+					return ("OUT_DVI_1280x1024_75");
+
+				case OUT_DVI_1360x768_60:
+					return ("OUT_DVI_1360x768_60");
+
+				case OUT_DVI_1366x768_60:
+					return ("OUT_DVI_1366x768_60");
+
+				case OUT_DVI_1400x1050_60:
+					return ("OUT_DVI_1400x1050_60");
+				case OUT_DVI_1400x1050_75:
+					return ("OUT_DVI_1400x1050_75");
+
+				case OUT_DVI_1440x900_60:
+					return ("OUT_DVI_1440x900_60");
+
+				case OUT_DVI_1440x1050_60:
+					return ("OUT_DVI_1440x1050_60");
+
+				case OUT_DVI_1600x900_60:
+					return ("OUT_DVI_1600x900_60");
+
+				case OUT_DVI_1600x1200_60:
+					return ("OUT_DVI_1600x1200_60");
+					
+				case OUT_DVI_1680x1050_60:
+					return ("OUT_DVI_1680x1050_60");
+					
+				case OUT_DVI_1920x1080_60:
+					return ("OUT_DVI_1920x1080_60");
+			}
+			break;
+			
+
+	} 
+
+
+	return str;
+
+}
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.h
new file mode 100644
index 0000000..d031396
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_intf.h
@@ -0,0 +1,243 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file  ch7036_intf.h
+* @version 1.2.5
+*-----------------------------------------------------------------------------
+*/
+
+
+
+#ifndef _CH7036_INTF_H_
+#define _CH7036_INTF_H_
+
+
+#include <config.h>
+#include <igd_pd.h>
+#include <pd.h>
+#include <pd_print.h>
+
+
+#include "ch7036_typedef.h"
+#include "ch7036_iic.h"
+#include "ch7036.h"
+
+#include "ch7036_fw.h"
+
+
+#include "config_.h"
+
+#ifdef T_LINUX
+#include "asm/div64.h"
+#endif
+
+
+#define internal_lvds_context_t lvds_context_t
+
+typedef unsigned char i2c_reg_t;
+
+
+
+#define DITHER_18_TO_18					0
+#define DITHER_18_TO_24					1
+#define DITHER_24_TO_18					2
+#define DITHER_24_TO_24					3
+
+
+#define DEFAULT_POSITION				2048
+#define DEFAULT_H_1080P_POSITION		2137
+#define HDMI_DEFAULT_UNDERSCAN			15
+#define CRT_DEFAULT_UNDERSCAN			18
+#define DEFAULT_ROTATE					0
+#define DEFAULT_HFLIP					0
+#define DEFAULT_VFLIP					0
+#define DEFAULT_TEXT_ENHANCE			7
+#define DEF_PLL_REF_DLY					0
+#define DEF_PLL_REF_FBDLY				1
+#define DEF_LVDS_TXDRV_CTRL				0
+#define DITHER_ENABLE					0
+#define DITHER_BYPASS					1
+#define MODE_6x4_BYPASS					0
+#define MODE_8x6_7x4_BYPASS				1
+
+
+typedef struct {
+    i2c_reg_t dev_D0 :1; 
+    i2c_reg_t dev_D1 :1;
+    i2c_reg_t dev_D2 :1;
+    i2c_reg_t dev_D3 :1; 
+    i2c_reg_t disp_D0:1; 
+    i2c_reg_t disp_D1:1; 
+    i2c_reg_t disp_D2:1; 
+    i2c_reg_t disp_D3:1; 
+} ch7036_power_states_t;
+
+
+
+typedef unsigned char ch7036_hpd_t;
+
+#define CH7036HPD_RESERVED1						0x01  //force port status inquiry bit
+#define CH7036HPD_CRT_ATTACHED					0x02 
+#define CH7036HPD_CRT_STATUS_CHANGED			0x04 
+#define CH7036HPD_CRT_EDID_PARSING_STATUS		0x08 
+
+#define CH7036HPD_RESERVED2						0x10 //incorrect display choice bit
+#define CH7036HPD_HDVI_ATTACHED					0x20 
+#define CH7036HPD_HDVI_STATUS_CHANGED			0x40 
+#define CH7036HPD_HDVI_EDID_PARSING_STATUS		0x80 
+
+
+typedef struct _ch7036_device_context {
+
+	
+	void						*internal_lvds;	
+	DEV_CONTEXT					*p_ch7xxx_context;  
+    pd_callback_t				*p_callback;
+
+	
+	pd_attr_t					*p_ch7036_attr_table;	
+	pd_attr_t					*p_lvds_attr_table;		
+
+	unsigned long				ch7036_num_attrs; 
+	unsigned long				lvds_num_attrs;	
+	
+	
+	HDMI_OUT_MODE 				hdmi_mode_index;
+	DVI_OUT_MODE 				dvi_mode_index;
+	CRT_OUT_MODE				crt_mode_index;
+
+	
+	pd_timing_t					*p_lvds_table; 
+	
+	
+	
+	
+	pd_timing_t					native_dtd; 
+
+	
+	unsigned short				fp_width;		
+	unsigned short				fp_height;		
+
+	unsigned char				dither_select; 
+
+	
+	unsigned long				pwr_state;		
+	
+	unsigned char				init_done;		
+	
+	
+
+
+	uint8						use_firmware; 
+
+	ch7036_hpd_t				hpd;
+	uint8						man_sel_out;  //auto or manually select display output channel
+
+	uint32						prev_outchannel;  
+	
+	void*						fw;
+	void*						cedid; 
+	void*						hedid; 
+	uint8						downscaled[2]; 
+	uint8						dwnscal_bypass; //1: remove 8x6,&7x4 when downscaling, 0: keep them
+	
+	uint32						last_emsg;	
+	
+} ch7036_device_context_t;
+
+
+
+
+#if 0
+#define PD_INTERNAL_LVDS_MODULE_OPEN(name, params) lvds_open params
+#define PD_INTERNAL_LVDS_MODULE_POST_SET_MODE(name, params) lvds_post_set_mode params
+#define PD_INTERNAL_LVDS_MODULE_SET_MODE(name, params) lvds_set_mode params
+#define PD_INTERNAL_LVDS_MODULE_SET_POWER(name, params) lvds_set_power params
+#define PD_INTERNAL_LVDS_MODULE_INIT_DEVICE(name, params) lvds_init_device params
+#define PD_INTERNAL_LVDS_MODULE_CLOSE(name, params) lvds_close params
+#define PD_INTERNAL_LVDS_MODULE_GET_ATTRIBUTES(name, params) lvds_get_attrs params
+#define PD_INTERNAL_LVDS_MODULE_SET_ATTRIBUTES(name, params) lvds_set_attrs params
+#define PD_INTERNAL_LVDS_MODULE_GET_TIMING_LIST(name, params) lvds_get_timing_list params
+
+#endif
+
+
+
+#define PD_INTERNAL_LVDS_MODULE_OPEN(name, params) internal_lvds_open params
+#define PD_INTERNAL_LVDS_MODULE_POST_SET_MODE(name, params) internal_lvds_post_set_mode params
+#define PD_INTERNAL_LVDS_MODULE_SET_MODE(name, params) internal_lvds_set_mode params
+#define PD_INTERNAL_LVDS_MODULE_SET_POWER(name, params) internal_lvds_set_power params
+#define PD_INTERNAL_LVDS_MODULE_GET_POWER(name, params) internal_lvds_get_power params
+#define PD_INTERNAL_LVDS_MODULE_INIT_DEVICE(name, params) internal_lvds_init_device params
+#define PD_INTERNAL_LVDS_MODULE_CLOSE(name, params) internal_lvds_close params
+#define PD_INTERNAL_LVDS_MODULE_GET_ATTRIBUTES(name, params) internal_lvds_get_attrs params
+#define PD_INTERNAL_LVDS_MODULE_SET_ATTRIBUTES(name, params) internal_lvds_set_attrs params
+#define PD_INTERNAL_LVDS_MODULE_GET_TIMING_LIST(name, params) internal_lvds_get_timing_list params
+#define PD_INTERNAL_LVDS_MODULE_SAVE(name, params) internal_lvds_save params
+#define PD_INTERNAL_LVDS_MODULE_RESTORE(name, params) internal_lvds_restore params
+#define PD_INTERNAL_LVDS_MODULE_GET_PORT_STATUS(name, params) internal_lvds_get_port_status params
+
+
+
+
+ch7036_status_t ch7036_device_prepare(ch7036_device_context_t* p_ctx);
+ch7036_status_t ch7036_device_config(ch7036_device_context_t* p_ctx);
+ch7036_status_t ch7036_device_start(ch7036_device_context_t* p_ctx);
+ch7036_status_t ch7036_device_set_power(ch7036_device_context_t* p_ctx,unsigned long channel);
+
+
+void ch7036_set_input_timing_info(ch7036_device_context_t *p_ctx,INPUT_INFO* pInput_Info);
+void ch7036_set_output_timing_info (ch7036_device_context_t *p_ctx, OUTPUT_INFO* pOutput_Info);
+void ch7036_set_prefer_timing_info(ch7036_device_context_t *p_ctx,PREFER_INFO* pPrefer_Info);
+
+
+
+ch7036_status_t ch7036_load_firmware(ch7036_device_context_t* p_ctx);
+ch7036_status_t ch7036_get_attached_device(ch7036_device_context_t* p_ctx);
+ch7036_status_t ch7036_read_edid(ch7036_device_context_t* p_ctx, uint32 channel);
+ch7036_status_t ch7036_get_hdvi_display_modes_supported(ch7036_device_context_t* p_ctx);
+
+
+uint8 * ch7036_get_mode_name(uint32 channel, uint8 index);
+//void ch7036_reset_edid_supported_modes(unsigned char *p_modes);
+ch7036_status_t ch7036_parse_edid(ch7036_device_context_t* p_ctx);
+ch7036_status_t ch7036_parse_cea_edid(ch7036_device_context_t* p_ctx);
+void ch7036_parse_cea_video_data_block(uint8 blk_size, uint8* p_buff, ch7036_edid_blk_t* p_edid);
+ch7036_status_t ch7036_set_edid_display_supported_attr(void *p_table, unsigned long num_attrs, unsigned char* p_downscaled, unsigned char* p_modes,int is_reset);
+void ch7036_alter_display_table(int all, void *p_table,unsigned char* p_modes, void* val,unsigned long* p_invis,unsigned char is_invis,unsigned char is_6x4);
+
+ch7036_status_t ch7036_parse_standard_edid(ch7036_device_context_t* p_ctx, uint32 channel);
+
+void ch7036_parse_standard_timing(ch7036_edid_blk_t* p_edid, unsigned char* p_addtional_st);
+
+void ch7036_parse_established_timing(ch7036_device_context_t* p_ctx, ch7036_edid_blk_t* p_edid);
+void ch7036_parse_detailed_descriptor_blocks(ch7036_device_context_t* p_ctx, ch7036_edid_blk_t* p_edid);
+void ch7036_parse_detailed_timing(OUT_FMT *p_dt, unsigned char* p_ebuf);
+
+
+void ch7036_reset_mcu(DEV_CONTEXT* p_ch_ctx);
+void ch7036_reset_datapath(DEV_CONTEXT* p_ch_ctx);
+void ch7036_reset(ch7036_device_context_t* p_ctx);
+
+extern uint32 GetLastErrorMessage(void);
+
+#endif  
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_pm.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_pm.c
new file mode 100755
index 0000000..d9f51bb
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_pm.c
@@ -0,0 +1,492 @@
+/*-----------------------------------------------------------------------------
+* 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/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.c
new file mode 100644
index 0000000..7d4e496
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.c
@@ -0,0 +1,1548 @@
+/*-----------------------------------------------------------------------------
+* 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/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.h
new file mode 100644
index 0000000..6798815
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_port.h
@@ -0,0 +1,59 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file  ch7036_port.h
+* @version 1.2.2
+*-----------------------------------------------------------------------------
+*/
+
+
+#ifndef _CH7036_PORT_H_
+#define _CH7036_PORT_H_
+
+
+
+#include "ch7036_intf.h"
+#include "ch7036_attr.h"
+
+int ch7036_open(pd_callback_t *p_callback, void **p_context);
+int ch7036_init_device(void *p_context);
+int ch7036_get_timing_list(void *p_context, pd_timing_t *p_in_list,
+	pd_timing_t **pp_out_list);
+int ch7036_set_mode(void *p_context, pd_timing_t *p_mode, unsigned long flags);
+int ch7036_post_set_mode(void *p_context, pd_timing_t *p_mode,
+	unsigned long flags);
+
+int ch7036_get_attributes(void *p_context, unsigned long *p_num_attr,
+	pd_attr_t **pp_list);
+int ch7036_set_attributes(void *p_context, unsigned long num_attr,
+	pd_attr_t *p_list);
+unsigned long ch7036_validate(unsigned long cookie);
+int ch7036_close(void *p_context);
+
+int ch7036_set_power(void *p_context, unsigned long state);
+int ch7036_get_power(void *p_context, unsigned long *p_state);
+int ch7036_save(void *p_context, void **pp_state, unsigned long flags);
+int ch7036_restore(void *p_context, void *p_state, unsigned long flags);
+int ch7036_get_port_status(void *context, pd_port_status_t *port_status);
+
+
+#endif 
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_reg_table.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_reg_table.c
new file mode 100755
index 0000000..126480f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_reg_table.c
@@ -0,0 +1,224 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file  ch7036_reg_table.c
+* @version 1.2.2
+*-----------------------------------------------------------------------------
+*/
+
+
+
+#include "ch7036_reg_table.h"
+
+
+
+
+MULTI_REG g_MultiRegTable[MUL_ID_END] = 
+{
+	{BASE_FLAG,       NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  3, 6,	NOOP_INDEX,   0, 7,		0},
+	
+	{HTI,		      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x0B,3, 6,	0x0D, 0, 7,		0},
+	{VTI,		      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x11,3, 5,	0x13, 0, 7,		0},
+	{HAI,		      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x0B,0, 2,	0x0C, 0, 7,		0},
+	{VAI,		      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x11,0, 2,	0x12, 0, 7,		0},
+	{HOI,		      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x0E,0, 2,	0x0F, 0, 7,		0},
+	{VOI,		      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x14,0, 2,	0x15, 0, 7,		0},
+	{HWI,		      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x0E,3, 5,	0x10, 0, 7,		0},
+	{VWI,		      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x14,3, 5,	0x16, 0, 7,		0},
+	{RCLK,            NOOP_INDEX,  0, 0,	0x0F,0, 1,  0x14,0, 7,  0x15, 0, 7,     4},
+	{DITHER_SEL1_SPP, NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x57, 7, 7,		4},	
+	{DITHER_SEL0_SPP, NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x57, 6, 6,		4},
+	{HSYNCP_SPP,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x41, 6, 6,		1},
+	{VSYNCP_SPP,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x41, 5, 5,		1},
+	{NP_INV0_SPP,     NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x58, 4, 4,		4},	
+	{NP_INV1_SPP,     NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x58, 3, 3,		4},	
+	{NP_INV2_SPP,     NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x58, 2, 2,		4},	
+	{NP_INV3_SPP,     NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x58, 1, 1,		4},	
+	{LVDS_IN_ORDER,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,	 0, 0,  NOOP_INDEX,  0, 0,  0x5F, 0, 0,		4},
+	
+	{LVDS0_SEQ_SPP,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x5E, 5, 7,		4},	
+	{LVDS1_SEQ_SPP,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x5E, 2, 4,		4},	
+	{LVDS2_SEQ_SPP,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,	 0, 0,  0x5F, 7, 7,		4},	
+	{LVDS3_SEQ_SPP,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x5F, 4, 6,		4},	
+	{LVDSCLK_SEQ_SPP, NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x5F, 1, 3,		4},	
+	{HSYNC_CNT_TH_SPP,NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x59, 5, 6,		4},	
+	{PRBS_SET_SEL_SPP,NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x61, 1, 1,		4},
+	{LVDS0_POL_SPP,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x59, 4, 4,		4},	
+    {LVDS1_POL_SPP,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x59, 3, 3,		4},	
+	{LVDS2_POL_SPP,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x59, 2, 2,		4},	
+	{LVDS3_POL_SPP,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x59, 1, 1,		4},	
+	{LVDSCLK_POL_SPP, NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x59, 0, 0,		4},	
+	
+	{HTO,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x1F,3, 6,	0x21, 0, 7,		0},
+	{VTO,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x25,3, 5,	0x27, 0, 7,		0},
+	{HAO,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x1F,0, 2,	0x20, 0, 7,		0},
+	{VAO,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x25,0, 2,	0x26, 0, 7,		0},
+	{HOO_HDMI,	      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x54,0, 2,	0x55, 0, 7,		0},
+	{VOO_HDMI,	      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x57,0, 2,	0x58, 0, 7,		0},
+	{HWO_HDMI,	      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x54,3, 5,	0x56, 0, 7,		0},
+	{VWO_HDMI,	      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x57,3, 5,	0x59, 0, 7,		0},
+	{HPO_I,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x19, 5, 5,		0},
+	{VPO_I,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x19, 4, 4,		0},
+	{DEPO_I,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x19, 3, 3,		0},
+	{HPO_O,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x2E, 4, 4,		0},
+	{VPO_O,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x2E, 3, 3,		0},
+	{DEPO_O,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x2E, 5, 5,		0},
+	
+	{HD_DVIB,	      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x0A, 2, 2,		0},
+	{INTLC,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x1E, 5, 5,		0},
+	{HD_LV_POL,       NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x4C, 5, 5,		0},
+	{HD_LV_SEQ,       NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x4C, 0, 4,		0},
+	{HDMI_LVDS_SEL,   NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x7E, 7, 7,		0},
+	{VSP,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x24, 5, 5,		1},
+	{HSP,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x24, 4, 4,		1},
+	{HDMIIN_HSP,	  NOOP_INDEX,  0, 0,    NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x61, 6, 6,		4},
+	{HDMIIN_VSP,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x61, 5, 5,		4},
+	{HDMIIN_DEP,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x61, 4, 4,		4},
+	{M1M0,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x3D, 2, 3,		0},
+	{C1C0,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x3D, 0, 1,		0},
+	{VIC,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x40, 0, 5,		0},
+	{COPY,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x4B, 6, 6,		0},
+	{SCAN_EN,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x6C, 0, 0,		4},
+	{HAO_SCL,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x6A,0, 7,	0x6B, 5, 7,		4},
+	{VAO_SCL,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x6B,0, 4,	0x6C, 2, 7,		4},
+	
+	{I2SPOL,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x1E, 7, 7,		0},
+	{I2S_SPDIFB,      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x1E, 6, 6,		0},
+	{I2S_LENGTH,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x1E, 2, 3,		0},
+	{I2SFMT,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x1E, 0, 1,		0},
+	{UCLK,            NOOP_INDEX,  0, 0,	0x0F,4, 5,  0x10,0, 7,  0x11, 0, 7 ,    4},
+	
+	{PCLK_NUM,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x28,  0, 7,0x29, 0, 7,		1},	
+	
+	{UCLKSEC,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x12, 4, 4,		1},
+	{PLL1N1,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x55, 3, 5,		4},	
+	{PLL1N2,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x55, 0, 2,		4},	
+	{PLL1N3,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x56, 5, 7,		4},	
+	{PLL3N8,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x13, 1, 2,		1},
+	{A2,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x5E, 0, 7,		0},
+	{MCLK,            NOOP_INDEX,  0, 0,	0x0F,2, 3,  0x12,0, 7,  0x13, 0, 7,     4},
+	{PLL2N5,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,  0x12,0, 1,	0x13, 7, 7,		1},
+	{PLL2N54,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x6E, 2, 2,		4},
+	{PLL2N53,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x6E, 1, 1,		4},
+	{PLL2N6,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x69, 5, 6,		4},
+	{PLL2N7,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x69, 3, 4,		4},
+	{DIVXTAL,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x6E, 3, 7,		4},
+	{A1,			  0x5A,0, 7,	0x5B,0, 7,	0x5C,0, 7,	0x5D, 0, 7,		0},
+	{A3,		      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x60, 0, 7,		4},
+	{TXPLL_FFD,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x67, 7, 7,		4},
+	{DRI_PLL_N1,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x0C, 3, 4,		1},
+	{DRI_PLL_N3,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x0C, 1, 2,		1},
+	{UCLKOD_SEL,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x61, 7, 7,		4},
+
+	{GCKSEL,          NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x54, 6, 6,		4},
+	{TSTEN1,          NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x14, 6, 6,		1},
+	
+	{LNSEL,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x68, 1, 2,		0},
+	{DAT16_32B,	      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x74, 7, 7,		0},
+	{TRUE24,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x74, 3, 3,		0},
+	{TRUE_COM,	      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x74, 4, 4,		0},
+	{WRLEN,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x2D, 6, 7,		0},
+	{ROTATE,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x2D, 4, 5,		0},
+	{HFLIP,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x2E, 7, 7,		0},
+	{VFLIP,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x2E, 6, 6,		0},
+	{DNSMPEN,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x25, 6, 6,		0},
+	{HADWSPP,	      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x60,0, 7,	0x61, 0, 2,		0},
+	{FLTBP2,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x32, 7, 7,		0},
+	{FLTBP1,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x32, 6, 6,		0},
+	{BLK_H,		      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x64, 0, 6,		0},
+	{FBA_INC,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x6B,0, 7,	0x6C, 0, 3,		0},
+	{SFM,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x6A, 0, 0,		0},
+	{THREN,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x6A, 2, 2,		0},
+	{THRRL,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x6D,0, 7,	0x6E, 0, 2,		0},
+	{WRFAST,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x6E, 3, 3,		0},
+	{CHG_HL,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x2F, 7, 7,		0},
+	{HINCA,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x2A,0, 7,	0x2B, 0, 2,		4},
+	{HINCB,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x2C,0, 7,	0x2D, 0, 2,		4},
+	{VINCA,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x2E,0, 7,	0x2F, 0, 2,		4},
+	{VINCB,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x30,0, 7,	0x31, 0, 2,		4},
+	{HDINCA,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x32,0, 7,	0x33, 0, 2,		4},
+	{HDINCB,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x34,0, 7,	0x35, 0, 2,		4},
+	{HINC,			  NOOP_INDEX,  0, 0,	0x36,0, 4,	0x37,0, 7,	0x38, 0, 7,		4},
+	{VINC,			  NOOP_INDEX,  0, 0,	0x39,0, 7,	0x3A,0, 7,  0x3B, 0, 7,		4},
+	{HDINC,		      NOOP_INDEX,  0, 0,	0x3C,0, 7,	0x3D,0, 7,	0x3E, 0, 7,		4},
+	{VSMST,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x70, 6, 7,		0},
+	{MEMINIT,	      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x0A, 7, 7,		0},
+	{STOP,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x0A, 4, 4,		0},
+	
+	{HDMI_PD,	      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x09, 0, 0,		0},
+	{I2S_PD,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x07, 6, 6,		0},
+	{SPDIF_PD,	      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x07, 0, 0,		0},
+	{DRI_PD,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x07, 3, 3,		0},
+	{DRI_PD_SER,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x16, 0, 0,		1},
+	{DRI_PD_PLL,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x16, 3, 3,		1}, 
+	{DRI_PDDRI,	      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x08, 4, 7,		0},
+	{CEC_PD,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x07, 4, 4,		0},
+	{PD_DDC,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x0E, 7, 7,		1},
+	
+	{LVDS_PD,	      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x0A, 3, 3,		0},
+	{RX_PD,		      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x63, 4, 7,		4},
+	{RXPLL_PD,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x64, 0, 0,		4},
+    {TXPLL_PD,		  NOOP_INDEX,  0, 0,    NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x66, 1, 1,		4},
+	{TXDRV_PD,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x11, 4, 4,		1},
+	{TXSER_PD,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x1A, 4, 4,		1}, 
+	
+	{VGA_PD,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x09, 2, 2,		0},
+	{PDDAC,		      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x08, 1, 3,		0},
+	{DACSENCE,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x57, 1, 1,		4},
+	{GCKOFF,          NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x09, 6, 6,		0},
+	{TV_BP,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x09, 5, 5,		0},
+	{PDPLL1,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x07, 1, 1,		0},
+	{PDPLL0,	      NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x54, 4, 4,		4},
+
+	{ICEN0,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x11, 7, 7,		1},
+
+	{PD_PROM,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x0F, 7, 7,		1},
+	{PDMIO,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x07, 2, 2,		0},
+	{PDIO,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x07, 5, 5,		0},
+	{HPD_PD,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x07, 7, 7,		0},
+	{SCLPD,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x09, 4, 4,		0},
+	{SDPD,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x09, 3, 3,		0},
+	{MEMPD,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x0A, 5, 5,		0},
+	{AUDDAC,          NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x5C, 2, 2,		4},
+	
+	{CRYS_FREQ_SPP,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,0x1C,	 0,	7,  0x1D, 0, 7,		0},
+	{I2SCK_SEC, 	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x07, 2, 2,		1},
+	{SP_EN,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x21, 7, 7,		1},
+	{HARD_SOFTB,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x58, 5, 5,		4},
+	{MULT_I2CEN,	  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x4E, 0, 0,		1},
+	{RXPLL_REFDLY,    NOOP_INDEX,  0, 0,    NOOP_INDEX,  0, 0,  NOOP_INDEX,  0, 0,  0x66, 5, 7,     4},
+	{RXPLL_FBDLY,     NOOP_INDEX,  0, 0,    NOOP_INDEX,  0, 0,  NOOP_INDEX,  0, 0,  0x66, 2, 4,     4},
+	{VFMT,            NOOP_INDEX,  0, 0,    NOOP_INDEX,  0, 0,  NOOP_INDEX,  0, 0,  0x2B, 0, 3,     0},
+
+	{DBP,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x19, 6, 6,		0},
+	{CK_TVINV,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x07, 1, 1,		1},
+	{DISPON,		  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x08, 0, 0,		1},
+
+	{VP,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x39,4, 7,	0x3B, 0, 7,		0},
+	{HP,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x39,0, 3,	0x3A, 0, 7,		0},
+
+	{TXTEN,			  NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x2E, 0, 2,		0},
+	{ZRCTS,           NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	NOOP_INDEX,  0, 0,	0x24, 1, 1,		1},
+	
+};
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_reg_table.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_reg_table.h
new file mode 100755
index 0000000..8e0c18d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_reg_table.h
@@ -0,0 +1,125 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file  ch7036_reg_table.h
+* @version 1.2
+*-----------------------------------------------------------------------------
+*/
+
+#ifndef _CH7036_REG_TABLE_H
+#define _CH7036_REG_TABLE_H
+
+#include "ch7036_typedef.h"
+
+typedef enum{
+	BASE_FLAG = 0,
+
+	
+	HTI,	VTI,	HAI,	VAI,	HOI,	VOI,	HWI,	VWI,	RCLK, 
+	DITHER_SEL1_SPP,		DITHER_SEL0_SPP,		HSYNCP_SPP,		VSYNCP_SPP,
+	NP_INV0_SPP,	NP_INV1_SPP,	NP_INV2_SPP,	NP_INV3_SPP,	LVDS_IN_ORDER,
+
+	
+	LVDS0_SEQ_SPP,	LVDS1_SEQ_SPP,	LVDS2_SEQ_SPP,	LVDS3_SEQ_SPP,	LVDSCLK_SEQ_SPP,
+	HSYNC_CNT_TH_SPP,				PRBS_SET_SEL_SPP,				
+	LVDS0_POL_SPP,	LVDS1_POL_SPP,	LVDS2_POL_SPP,	LVDS3_POL_SPP,	LVDSCLK_POL_SPP,		
+
+	
+	HTO,	VTO,	HAO,	VAO,	HOO_HDMI,		VOO_HDMI,		HWO_HDMI,	VWO_HDMI,	
+	HPO_I,	VPO_I,	DEPO_I,	HPO_O,	VPO_O,			DEPO_O,	
+
+	
+	HD_DVIB,		INTLC,			HD_LV_POL,		HD_LV_SEQ,		HDMI_LVDS_SEL, 
+	VSP,			HSP,			HDMIIN_HSP,		HDMIIN_VSP,		HDMIIN_DEP,
+	M1M0,			C1C0,			VIC,
+	COPY,			SCAN_EN,		HAO_SCL,		VAO_SCL,
+
+	
+	I2SPOL,			I2S_SPDIFB,		I2S_LENGTH,		I2SFMT,		
+	UCLK,			PCLK_NUM,
+
+	
+	UCLKSEC,		PLL1N1,			PLL1N2,			PLL1N3,			PLL3N8,		A2,			MCLK, 
+	PLL2N5,			PLL2N54,		PLL2N53,		PLL2N6,			PLL2N7,		DIVXTAL,
+	A1,				A3,				TXPLL_FFD,		DRI_PLL_N1,		DRI_PLL_N3, UCLKOD_SEL,
+	GCKSEL,         TSTEN1, 
+
+	
+	LNSEL,			DAT16_32B,		TRUE24,			TRUE_COM,		WRLEN,	
+	ROTATE,			HFLIP,			VFLIP,
+	DNSMPEN,		HADWSPP,		FLTBP2,			FLTBP1,			BLK_H,
+	FBA_INC,		SFM,			THREN,			THRRL,			WRFAST,		CHG_HL,
+	HINCA,			HINCB,			VINCA,			VINCB,			HDINCA,		HDINCB,
+	HINC,			VINC,			HDINC,
+	VSMST,			MEMINIT,		STOP,						
+	
+	
+	HDMI_PD,		I2S_PD,			SPDIF_PD,		DRI_PD,			DRI_PD_SER,
+	DRI_PD_PLL,		DRI_PDDRI,		CEC_PD,			PD_DDC,	
+	LVDS_PD,		RX_PD,			RXPLL_PD,		TXPLL_PD,		TXDRV_PD,	TXSER_PD,	
+	VGA_PD,			PDDAC,			DACSENCE,       GCKOFF, 
+	TV_BP,			PDPLL1,			PDPLL0,			ICEN0,			PD_PROM,		PDMIO,		PDIO,		HPD_PD,
+	SCLPD,			SDPD,			MEMPD,			AUDDAC,
+
+	
+	CRYS_FREQ_SPP,	I2SCK_SEC,		SP_EN,			HARD_SOFTB,		MULT_I2CEN,	RXPLL_REFDLY,
+	RXPLL_FBDLY, VFMT,
+
+	
+	DBP,			CK_TVINV,		DISPON,
+	
+	VP,	HP,
+	
+	TXTEN,
+	ZRCTS,
+	
+	MUL_ID_END,
+	
+}MULTI_REG_ID;
+
+typedef struct{
+	MULTI_REG_ID RegId;
+	uint8 TopRegIndex;
+	uint8 TopStartBit;
+	uint8 TopEndBit;
+	uint8 HighRegIndex;
+	uint8 HighStartBit;
+	uint8 HighEndBit;
+	uint8 MiddleRegIndex;
+	uint8 MiddleStartBit;
+	uint8 MiddleEndBit;
+	uint8 LowRegIndex;
+	uint8 LowStartBit;
+	uint8 LowEndBit;
+	uint8 PageIndex;
+}MULTI_REG, *PMULTI_REG;
+
+extern MULTI_REG g_MultiRegTable[];
+
+//issue- 11/15/11- thua 
+//Intel C compiler complained negative constant (-1) comparison to unsigned char for checked build verion
+//for free build, these warnings are treated as compiling error
+//solution:
+//define NOOP_REGINDEX as 2-complement of -1
+#define NOOP_INDEX 0xFF
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_typedef.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_typedef.h
new file mode 100755
index 0000000..57c987b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/ch7036_typedef.h
@@ -0,0 +1,472 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file  ch7036_typedef.h
+* @version 1.2
+*-----------------------------------------------------------------------------
+*/
+
+
+#ifndef _CH7036_TYPEDEF_H
+#define _CH7036_TYPEDEF_H
+
+
+
+typedef unsigned char				uint8;
+typedef unsigned short				uint16;
+typedef unsigned int				uint32;
+
+
+
+typedef unsigned long long int 		uint64;
+
+typedef signed char					int8;
+typedef signed short				int16;
+typedef signed int					int32;
+
+typedef signed long long int		int64;
+
+
+
+
+
+
+
+typedef uint32					ch_bool;
+#define ch_true					1
+#define ch_false				0
+
+
+
+typedef struct{
+	uint16 ht;
+	uint16 ha;
+	uint16 ho;
+	uint16 hw;
+	uint16 vt;
+	uint16 va;
+	uint16 vo;
+	uint16 vw;
+	uint16 hz;  
+	uint16 stype; 
+
+}TIMING, *PTIMING;
+
+
+#define PIXEL_FMT_18BIT		0
+#define PIXEL_FMT_24BIT		1
+
+#define POL_HIGH			1
+#define POL_LOW				0
+#define POL_INVERT			1
+#define POL_NO_INV			0
+
+#define AUDIO_I2S			1
+#define AUDIO_SPDIF			0
+
+#define SCANTYPE_INTERLACED		0
+#define SCANTYPE_PROGRESSIVE	1
+#define TIMING_LIST_END			2
+
+typedef struct{
+	
+	TIMING timing;
+	uint32 rx_clk_khz;
+	uint8  pixel_fmt;	
+	uint8  hs_pol;		
+	uint8  vs_pol;
+	uint8  de_pol;
+	uint8  data_ch_pol;	
+	uint8  data_ch_invert;
+	
+	uint8  audio_type;	
+	uint8  i2s_pol;
+	uint8  i2s_len;
+	uint8  i2s_fmt;
+}INPUT_INFO, *PINPUT_INFO;
+
+
+
+
+#define LVDS_DATA0_SEL			0
+#define LVDS_DATA1_SEL			1
+#define LVDS_DATA2_SEL			2
+#define LVDS_DATA3_SEL			3
+#define LVDS_CLOCK_SEL			4
+
+
+#define LVDS_CHANNEL_SWAP_DEF		(LVDS_DATA0_SEL << 0) | (LVDS_DATA1_SEL << 4) | (LVDS_DATA2_SEL << 8) | (LVDS_DATA3_SEL << 12) | (LVDS_CLOCK_SEL << 16)
+#define LVDS_CHANNEL_SWAP_OP1		(LVDS_DATA1_SEL << 0) | (LVDS_DATA2_SEL << 4) | (LVDS_DATA3_SEL << 8) | (LVDS_CLOCK_SEL << 12) | (LVDS_DATA0_SEL << 16)
+#define LVDS_CHANNEL_SWAP_OP2		(LVDS_DATA2_SEL << 0) | (LVDS_DATA3_SEL << 4) | (LVDS_CLOCK_SEL << 8) | (LVDS_DATA0_SEL << 12) | (LVDS_DATA1_SEL << 16)
+#define LVDS_CHANNEL_SWAP_OP3		(LVDS_DATA3_SEL << 0) | (LVDS_CLOCK_SEL << 4) | (LVDS_DATA0_SEL << 8) | (LVDS_DATA1_SEL << 12) | (LVDS_DATA2_SEL << 16)
+#define LVDS_CHANNEL_SWAP_OP4		(LVDS_CLOCK_SEL << 0) | (LVDS_DATA0_SEL << 4) | (LVDS_DATA1_SEL << 8) | (LVDS_DATA2_SEL << 12) | (LVDS_DATA3_SEL << 16)
+#define LVDS_CHANNAL_SWAP_OP5		(LVDS_DATA3_SEL << 0) | (LVDS_CLOCK_SEL << 4) | (LVDS_DATA2_SEL << 8) | (LVDS_DATA1_SEL << 12) | (LVDS_DATA0_SEL << 16)
+
+typedef struct{
+	uint32 channel_swap;	
+	uint32 channel_pol;		
+	uint32 pixel_fmt;		
+}LVDS_FMT, *PLVDS_FMT;
+
+#define AS_RATIO_4_3		1
+#define AS_RATIO_16_9		2
+
+typedef struct{
+	uint8 is_dvi_mode;		
+	uint8 format_index;		
+	uint8 aspect_ratio;		
+	uint8 channel_swap;		
+	uint8 data_pol_invert;	
+	uint8 hs_pol;			
+	uint8 vs_pol;			
+	uint8 protect_enable;	
+}HDMI_FMT, *PHDMI_FMT;
+
+typedef struct{
+	uint8 channel_swap;		
+	uint8 hs_pol;			
+	uint8 vs_pol;			
+	uint8 de_pol;			
+}VGA_FMT, *PVGA_FMT;
+
+
+#define CHANNEL_LVDS		(1 << 0)
+#define CHANNEL_HDMI		(1 << 1)
+#define CHANNEL_VGA			(1 << 2)
+#define CHANNEL_DVI			(1 << 3)
+#define CHANNEL_LVDS_HDMI 	(CHANNEL_LVDS | CHANNEL_HDMI)
+#define CHANNEL_LVDS_VGA 	(CHANNEL_LVDS | CHANNEL_VGA)
+#define CHANNEL_LVDS_DVI 	(CHANNEL_LVDS | CHANNEL_DVI)  
+#define CHANNEL_AUTO_DETECT	0x10 
+
+
+#define CHANNEL_LVDS_HDMI_VGA_OFF	0x0000  
+
+
+
+#define ROTATE_0			0
+#define ROTATE_NO			0
+#define ROTATE_90			1
+#define ROTATE_180			2
+#define ROTATE_270			3
+
+typedef struct{
+	uint32 channel;			
+	LVDS_FMT lvds_fmt;		
+	HDMI_FMT hdmi_fmt;		
+	VGA_FMT vga_fmt;		
+	TIMING timing;			
+	uint32 uclk_khz;		
+	uint8  ds_percent_h;	
+	uint8  ds_percent_v;	
+	uint8  rotate;			
+	uint8  h_flip;			
+	uint8  v_flip;			
+	uint16  h_position;			
+	uint16  v_position;			
+}OUTPUT_INFO, *POUTPUT_INFO;
+
+
+#define HS_TOLERANCE_LEVEL0			0
+#define HS_TOLERANCE_LEVEL1			1
+#define HS_TOLERANCE_LEVEL2			3
+#define HS_TOLERANCE_LEVEL3			7
+
+#define RST_BIT_HSYNC				0
+#define RST_BIT_VSYNC				1
+
+#define MEM_CLK_FREQ_MAX			166000	
+#define FBA_INC_MAX					3000	
+
+#define THRRL_ADJUST_DEF			200	
+
+#define THRRL_ADJUST_OP1			250		
+#define THRRL_ADJUST_OP2			300		
+
+typedef struct{
+	uint32 mclk_khz;		
+	
+	uint8 uclkod_sel;		
+	uint8 dat16_32b;		
+	uint8 true24;			
+	uint8 true_com;			
+	
+	uint8 lvds_out_hs_tolerance;	
+	uint8 lvds_out_reset_bit_sel;	
+	
+	uint8 dither_filter_enable;		
+	uint8 hscale_ratio_gate;		
+	
+	uint8 scale_line_adjust;		
+	uint8  text_enhancement;	
+			
+	uint8 pll_ref_dly;
+	uint8 pll_ref_fbdly;
+	uint8 lvds_txdrv_ctrl;
+
+	uint8 eye_bgtrim ;
+	uint8 eye_dacg;
+	uint8 eye_dri_demp;
+	uint8 eye_dri_pll_cp;
+	uint8 eye_dri_damp;
+	uint8 eye_dri_pll_rlf;
+	uint8 eye_rdac;
+	
+	uint8 reset; 
+	uint8 vga_enable;
+
+}PREFER_INFO, *PPREFER_INFO;
+
+
+
+typedef struct{
+	uint32 DeviceID;
+	INPUT_INFO* pInput_Info;
+	OUTPUT_INFO* pOutput_Info;
+	PREFER_INFO* pPrefer_Info;
+	void*	pd_context; 
+}DEV_CONTEXT, *PDEV_CONTEXT;
+
+typedef struct{
+	uint32 fmt_index;
+	uint32 clk_freq;
+	uint32 aspect;
+	TIMING timing;
+}OUT_FMT, *POUT_FMT;
+
+typedef enum hdmi{
+
+	OUT_HDMI_640x480P_59 = 0,
+	OUT_HDMI_640x480P_60,
+
+	OUT_HDMI_720x480P_59,
+	OUT_HDMI_720x480P_60, 
+
+	OUT_HDMI_720x576P_50,
+
+	OUT_HDMI_1280x720P_59,
+	OUT_HDMI_1280x720P_60, 
+
+	OUT_HDMI_1920x1080I_59, 
+	OUT_HDMI_1920x1080I_60, 
+
+	OUT_HDMI_1920x1080P_59,
+	OUT_HDMI_1920x1080P_60, 
+
+//	OUT_HDMI_720x576P_50, //2/2/12 grouped to downscaling modes < 13x7
+	OUT_HDMI_1280x720P_50,
+	OUT_HDMI_1920x1080I_50,
+	
+	OUT_HDMI_1920x1080P_50,
+
+	OUT_HDMI_1920x1080P_23,
+	OUT_HDMI_1920x1080P_24,
+	OUT_HDMI_1920x1080P_25,
+	OUT_HDMI_1920x1080P_29,
+	OUT_HDMI_1920x1080P_30,
+
+	OUT_HDMI_1920x1080I_100,
+	OUT_HDMI_1280x720P_100,
+	OUT_HDMI_720x576P_100,
+	
+	OUT_HDMI_1920x1080I_119,
+	OUT_HDMI_1920x1080I_120,
+    
+	OUT_HDMI_1280x720P_119,
+	OUT_HDMI_1280x720P_120,
+
+	OUT_HDMI_720x480P_119,
+	OUT_HDMI_720x480P_120,
+
+	OUT_HDMI_720x576P_200,
+    OUT_HDMI_1280x720P_239,
+	OUT_HDMI_1280x720P_240, 
+	OUT_HDMI_END,
+}HDMI_OUT_MODE;
+
+typedef enum dvi {
+
+	OUT_DVI_640x480_60 = 0,
+
+	OUT_DVI_640x480_72,
+	OUT_DVI_640x480_75,
+	OUT_DVI_720x400_70,
+
+	OUT_DVI_800x600_56,
+    OUT_DVI_800x600_60,
+	OUT_DVI_800x600_72,
+	OUT_DVI_800x600_75,
+
+	OUT_DVI_1024x768_60,
+	OUT_DVI_1024x768_70,
+	OUT_DVI_1024x768_75,
+
+    OUT_DVI_1152x864_60,
+    OUT_DVI_1280x720_60,
+	OUT_DVI_1280x800_60,
+	OUT_DVI_1280x960_60,
+	OUT_DVI_1280x1024_60,
+	OUT_DVI_1280x1024_75,
+	OUT_DVI_1360x768_60,
+	OUT_DVI_1366x768_60,
+
+	OUT_DVI_1400x1050_60,
+	OUT_DVI_1400x1050_75, 
+	
+
+	OUT_DVI_1440x900_60,
+	OUT_DVI_1440x1050_60,
+	OUT_DVI_1600x900_60,
+	OUT_DVI_1600x1200_60,
+	OUT_DVI_1680x1050_60,
+
+	OUT_DVI_1920x1080_60, 
+
+	OUT_DVI_1920x1200_60, 
+
+	OUT_DVI_END,
+} DVI_OUT_MODE;
+
+typedef enum crt{
+
+	OUT_CRT_640x400_85 = 0,
+
+	OUT_CRT_640x480_60,
+	
+	OUT_CRT_640x480_72,
+	OUT_CRT_640x480_75,
+	OUT_CRT_640x480_85,
+	
+	OUT_CRT_720x400_85,
+
+	OUT_CRT_800x600_56,
+
+	    
+	OUT_CRT_800x600_60, 
+	OUT_CRT_800x600_72,
+	OUT_CRT_800x600_75,
+	OUT_CRT_800x600_85, 
+
+	OUT_CRT_1024x768_60,
+	OUT_CRT_1024x768_70,
+	OUT_CRT_1024x768_75, 
+	OUT_CRT_1024x768_85, 
+	
+
+	
+	OUT_CRT_1152x864_75,
+	
+	OUT_CRT_1280x768_60,  
+	OUT_CRT_1280x768_75,  
+	OUT_CRT_1280x768_85,  
+	
+	OUT_CRT_1280x960_60,
+	OUT_CRT_1280x960_85, 
+
+	OUT_CRT_1280x1024_60,
+	OUT_CRT_1280x1024_75,
+	OUT_CRT_1280x1024_85, 
+
+	OUT_CRT_1360x768_60,   
+
+	OUT_CRT_1400x1050_60,
+	OUT_CRT_1400x1050_75,
+	
+
+
+	OUT_CRT_1440x900_60,
+	OUT_CRT_1440x1050_60,
+
+	OUT_CRT_1600x900_60, 
+	OUT_CRT_1600x1200_60,  
+	
+	OUT_CRT_1920x1080_60, 
+
+	
+
+	OUT_CRT_END,
+}CRT_OUT_MODE;
+
+#define MAX_ATTR_LIST_SIZE 32
+
+
+
+
+#define ERR_NO_ERROR						0
+
+#define ERR_DEVICE_PREPARE					100
+#define ERR_RESOLUTION_H_ODD				101
+#define ERR_RESOLUTION_V_ODD				102
+#define ERR_BANDWIDTH_OVERFLOW				103
+#define ERR_RESOLUTION_OVERFLOW				104
+#define ERR_DEVICE_NO_EXIST					105
+#define ERR_NO_SUPPORT_TRUE24				106
+#define ERR_NO_SUPPORT_TRUECOM				107
+#define ERR_ROTATION_WITH_VAI				108 
+#define ERR_FLIP_WITH_VAI					109
+
+#define ERR_DEVICE_CONFIG					200
+#define ERR_ASPECT_RATIO_NOMATCH			201
+#define ERR_PLL1N2_WRONG					202
+#define ERR_PLL1N3_WRONG					203
+#define ERR_PLL1N1_WRONG					204
+#define ERR_PLL3N8_WRONG					205
+#define ERR_PLL2N5_WRONG					206
+#define ERR_PLL2N6_WRONG					207
+#define ERR_PLL2N7_WRONG					208
+#define ERR_DMXTAL_WRONG					209
+#define ERR_HDMI_CLOCK_NO_SUPPORT			210	
+
+#define ERR_DEVICE_RUNNING					300
+#define ERR_CAL_INC_DIV_ZERO				301		
+#define	ERR_CAL_INC_NO_MATH					302
+
+
+
+typedef enum {
+    SS_POWER_ON_STATE,       
+    SS_SUCCESS,              
+    SS_NOT_SUPPORTED,        
+    SS_INVALID_ARGUMENT,     
+    SS_PENDING,              
+    SS_TARGET_UNSPECIFIED,   
+    SS_SCALING_UNSUPPORTED,  
+
+	SS_MEM_ALLOC_ERR,
+
+    
+    SS_UNSUCCESSFUL = 10,    
+    SS_INVALID_RETURN,       
+    SS_WRITE_FAILED,         
+    SS_READ_FAILED,          
+
+	SS_FIRMWARE_ERR,
+	SS_FIRMWARE_TIMEOUT,
+
+	SS_CRT_HPD_NOTCONNECTED,
+	SS_CRT_HPD_CONNECTED_TO_GRD,
+	SS_DISPLAY_CHOICE_NOT_ALLOWED,
+
+
+} ch7036_status_t;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/config_.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/config_.h
new file mode 100644
index 0000000..99949e8
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/config_.h
@@ -0,0 +1,73 @@
+/*-----------------------------------------------------------------------------
+* Copyright (c) Chrontel Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+*-----------------------------------------------------------------------------
+* @file  config_.h
+* @version 1.2.3
+*-----------------------------------------------------------------------------
+*/
+
+#ifndef _CONFIG_H_
+#define _CONFIG_H_
+
+
+#define T_LVDS_OPEN
+#define T_LVDS_INIT
+#define T_POST_SETMODE
+#define T_LVDS_CLOSE
+
+#define T_SET_TIMING
+
+#define T_PD_DISPLAY_LVDS_INT 
+
+#define T_DEVICE_DETECTION 
+#define T_RES_DEALLOC
+
+#define T_TEST_HW
+#define T_RESET
+
+
+#define T_HDMI_TIMING_TABLE
+#define T_VGA_TIMING_TABLE
+#define T_PANEL_NATIVE_DTD
+
+
+#define T_LH_POWER_ON_OFF
+
+#define T_CH7036_USE_LVDS_ATTR_TABLE
+
+#define T_CH7036_INIT_ATTR_TABLE
+
+
+#define T_CH7036_USE_FIRMWARE
+
+#define T_CH7036_EDID_DUMP
+#undef T_CH7036_EDID_DUMP
+
+#define T_SHOW_EDID_DISPLAY_ATTR
+#undef T_SHOW_EDID_DISPLAY_ATTR
+
+#define T_LINUX
+//#undef T_LINUX
+
+#define T_CONFIG_PLB
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/edid7036.car b/drivers/gpu/drm/emgd/emgd/pal/ch7036/edid7036.car
new file mode 100644
index 0000000..b7da904
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/edid7036.car
@@ -0,0 +1,3362 @@
+unsigned char lhfm_array[]= {
+	0x02,
+	0x0D,
+	0x14,
+	0x02,
+	0x0A,
+	0xBC,
+	0xFF,
+	0xFF,
+	0xFF,
+	0xFF,
+	0xFF,
+	0x02,
+	0x09,
+	0x83,
+	0x75,
+	0x50,
+	0x66,
+	0xE4,
+	0xF5,
+	0x26,
+	0xF5,
+	0x27,
+	0xC2,
+	0x01,
+	0xF5,
+	0x25,
+	0xF5,
+	0x28,
+	0xFF,
+	0x12,
+	0x09,
+	0xF4,
+	0x40,
+	0x01,
+	0x22,
+	0xE5,
+	0x50,
+	0x24,
+	0x3E,
+	0xF8,
+	0xE6,
+	0xF5,
+	0x4A,
+	0x7B,
+	0x02,
+	0x7D,
+	0x23,
+	0xE4,
+	0xFF,
+	0x12,
+	0x09,
+	0x15,
+	0x40,
+	0x01,
+	0x22,
+	0xA8,
+	0x50,
+	0xE6,
+	0x30,
+	0xE0,
+	0x03,
+	0x43,
+	0x28,
+	0x01,
+	0xE8,
+	0x04,
+	0xF8,
+	0xE6,
+	0xFF,
+	0x54,
+	0x0E,
+	0x60,
+	0x03,
+	0x43,
+	0x28,
+	0x02,
+	0xEF,
+	0x30,
+	0xE0,
+	0x03,
+	0x43,
+	0x28,
+	0x04,
+	0x75,
+	0x4B,
+	0x26,
+	0xE4,
+	0xF5,
+	0x4F,
+	0x7B,
+	0x02,
+	0xAD,
+	0x4B,
+	0xE4,
+	0xFF,
+	0x12,
+	0x09,
+	0x15,
+	0x50,
+	0x36,
+	0x05,
+	0x4B,
+	0x05,
+	0x4B,
+	0xA8,
+	0x50,
+	0xE6,
+	0xFF,
+	0xB4,
+	0x01,
+	0x08,
+	0xE8,
+	0x04,
+	0xF8,
+	0xE6,
+	0x64,
+	0x01,
+	0x60,
+	0x23,
+	0xE5,
+	0x50,
+	0x04,
+	0xF8,
+	0x74,
+	0xC0,
+	0x56,
+	0xF6,
+	0xEF,
+	0xB4,
+	0x81,
+	0x09,
+	0xE5,
+	0x50,
+	0x04,
+	0xF8,
+	0x76,
+	0x80,
+	0x43,
+	0x28,
+	0x04,
+	0xA8,
+	0x50,
+	0xE6,
+	0xB4,
+	0xA9,
+	0x08,
+	0xE8,
+	0x04,
+	0xF8,
+	0x76,
+	0x40,
+	0x43,
+	0x28,
+	0x10,
+	0x05,
+	0x4F,
+	0xE5,
+	0x4F,
+	0xC3,
+	0x94,
+	0x08,
+	0x40,
+	0xB6,
+	0x7B,
+	0x06,
+	0x7D,
+	0x38,
+	0xE4,
+	0xFF,
+	0x12,
+	0x09,
+	0x15,
+	0x40,
+	0x03,
+	0x02,
+	0x01,
+	0x30,
+	0xE5,
+	0x50,
+	0x24,
+	0x02,
+	0xF8,
+	0xE6,
+	0x54,
+	0xF0,
+	0xFF,
+	0xE5,
+	0x50,
+	0x04,
+	0xF8,
+	0xA6,
+	0x07,
+	0xE5,
+	0x50,
+	0x24,
+	0x03,
+	0xF8,
+	0xE6,
+	0xFF,
+	0xE5,
+	0x50,
+	0x24,
+	0x02,
+	0xF8,
+	0xA6,
+	0x07,
+	0xE5,
+	0x50,
+	0x24,
+	0x05,
+	0xF8,
+	0xE6,
+	0x54,
+	0xF0,
+	0xFF,
+	0xE5,
+	0x50,
+	0x24,
+	0x03,
+	0xF8,
+	0xA6,
+	0x07,
+	0xE4,
+	0xF5,
+	0x4F,
+	0xE4,
+	0xF5,
+	0x4C,
+	0xE5,
+	0x4F,
+	0x75,
+	0xF0,
+	0x05,
+	0xA4,
+	0x24,
+	0xBA,
+	0xF5,
+	0x82,
+	0xE4,
+	0x34,
+	0x05,
+	0xF5,
+	0x83,
+	0xE5,
+	0x82,
+	0x25,
+	0x4C,
+	0xF5,
+	0x82,
+	0xE4,
+	0x35,
+	0x83,
+	0xF5,
+	0x83,
+	0xE4,
+	0x93,
+	0xFF,
+	0xE5,
+	0x50,
+	0x25,
+	0x4C,
+	0xF8,
+	0xE6,
+	0xB5,
+	0x07,
+	0x07,
+	0x05,
+	0x4C,
+	0xE5,
+	0x4C,
+	0xB4,
+	0x04,
+	0xD3,
+	0xE5,
+	0x4C,
+	0xB4,
+	0x04,
+	0x13,
+	0xE5,
+	0x4F,
+	0x75,
+	0xF0,
+	0x05,
+	0xA4,
+	0x24,
+	0xBF,
+	0xF5,
+	0x82,
+	0xE4,
+	0x34,
+	0x05,
+	0xF5,
+	0x83,
+	0xE4,
+	0x93,
+	0x42,
+	0x28,
+	0x05,
+	0x4F,
+	0xE5,
+	0x4F,
+	0xB4,
+	0x03,
+	0xB1,
+	0xD2,
+	0x04,
+	0xE5,
+	0x4A,
+	0x70,
+	0x02,
+	0xC3,
+	0x22,
+	0x75,
+	0x4F,
+	0x01,
+	0xE5,
+	0x4F,
+	0xD3,
+	0x95,
+	0x4A,
+	0x40,
+	0x03,
+	0x02,
+	0x02,
+	0x61,
+	0xE5,
+	0x4F,
+	0x30,
+	0xE0,
+	0x04,
+	0x7F,
+	0x80,
+	0x80,
+	0x02,
+	0x7F,
+	0x00,
+	0x8F,
+	0x51,
+	0xAF,
+	0x4F,
+	0x12,
+	0x09,
+	0xF4,
+	0x40,
+	0x01,
+	0x22,
+	0xE5,
+	0x4F,
+	0xC3,
+	0x13,
+	0xF5,
+	0x4E,
+	0x7B,
+	0x05,
+	0xAD,
+	0x51,
+	0xFF,
+	0x12,
+	0x09,
+	0x15,
+	0x40,
+	0x01,
+	0x22,
+	0xA8,
+	0x50,
+	0xE6,
+	0x64,
+	0x02,
+	0x60,
+	0x03,
+	0x02,
+	0x02,
+	0x5C,
+	0xE8,
+	0x04,
+	0xF8,
+	0xE6,
+	0x64,
+	0x03,
+	0x60,
+	0x03,
+	0x02,
+	0x02,
+	0x5C,
+	0xE5,
+	0x50,
+	0x24,
+	0x02,
+	0xF8,
+	0xE6,
+	0xFF,
+	0xD3,
+	0x94,
+	0x04,
+	0x50,
+	0x03,
+	0x02,
+	0x02,
+	0x5C,
+	0x8F,
+	0x4B,
+	0xE5,
+	0x50,
+	0x24,
+	0x04,
+	0xF8,
+	0xE6,
+	0xF5,
+	0x4C,
+	0x75,
+	0x4D,
+	0x04,
+	0xE5,
+	0x4C,
+	0x54,
+	0xE0,
+	0x64,
+	0x60,
+	0x70,
+	0x37,
+	0xE5,
+	0x4D,
+	0x7B,
+	0x06,
+	0x12,
+	0x09,
+	0x10,
+	0x40,
+	0x01,
+	0x22,
+	0xE5,
+	0x50,
+	0x04,
+	0xF8,
+	0xE6,
+	0x64,
+	0x03,
+	0x70,
+	0x24,
+	0xE5,
+	0x50,
+	0x24,
+	0x02,
+	0xF8,
+	0xE6,
+	0x64,
+	0x0C,
+	0x70,
+	0x1A,
+	0xE5,
+	0x50,
+	0x24,
+	0x03,
+	0xF8,
+	0xE6,
+	0x70,
+	0x12,
+	0xE5,
+	0x50,
+	0x24,
+	0x04,
+	0xF8,
+	0xE6,
+	0xF5,
+	0x26,
+	0xE5,
+	0x50,
+	0x24,
+	0x05,
+	0xF8,
+	0xE6,
+	0xF5,
+	0x27,
+	0xD2,
+	0x01,
+	0xE5,
+	0x4C,
+	0x54,
+	0xE0,
+	0x64,
+	0x40,
+	0x70,
+	0x59,
+	0xE5,
+	0x4C,
+	0x54,
+	0x1F,
+	0xF5,
+	0x52,
+	0xE5,
+	0x4D,
+	0x25,
+	0x51,
+	0x04,
+	0xFD,
+	0xAB,
+	0x52,
+	0xAF,
+	0x4E,
+	0x12,
+	0x09,
+	0x15,
+	0x50,
+	0x64,
+	0xE4,
+	0xF5,
+	0x53,
+	0xE5,
+	0x53,
+	0xC3,
+	0x95,
+	0x52,
+	0x50,
+	0x3A,
+	0xE4,
+	0xF5,
+	0x54,
+	0xE5,
+	0x50,
+	0x25,
+	0x53,
+	0xF8,
+	0xE6,
+	0x54,
+	0x7F,
+	0xFF,
+	0xE5,
+	0x54,
+	0x25,
+	0xE0,
+	0x24,
+	0xA6,
+	0xF5,
+	0x82,
+	0xE4,
+	0x34,
+	0x05,
+	0xF5,
+	0x83,
+	0xE4,
+	0x93,
+	0xB5,
+	0x07,
+	0x11,
+	0xE5,
+	0x54,
+	0x25,
+	0xE0,
+	0x24,
+	0xA7,
+	0xF5,
+	0x82,
+	0xE4,
+	0x34,
+	0x05,
+	0xF5,
+	0x83,
+	0xE4,
+	0x93,
+	0x42,
+	0x25,
+	0x05,
+	0x54,
+	0xE5,
+	0x54,
+	0xB4,
+	0x0A,
+	0xCD,
+	0x05,
+	0x53,
+	0x80,
+	0xBF,
+	0xE5,
+	0x4C,
+	0x54,
+	0x1F,
+	0x25,
+	0x4D,
+	0x04,
+	0xF5,
+	0x4D,
+	0x7B,
+	0x01,
+	0x12,
+	0x09,
+	0x10,
+	0x40,
+	0x01,
+	0x22,
+	0xA8,
+	0x50,
+	0xE6,
+	0xF5,
+	0x4C,
+	0xE5,
+	0x4D,
+	0xC3,
+	0x95,
+	0x4B,
+	0x50,
+	0x03,
+	0x02,
+	0x01,
+	0x9C,
+	0x05,
+	0x4F,
+	0x02,
+	0x01,
+	0x3B,
+	0xA2,
+	0x01,
+	0x22,
+	0xE4,
+	0xF5,
+	0xA8,
+	0xF5,
+	0xA0,
+	0x75,
+	0x90,
+	0xC0,
+	0xD2,
+	0x8A,
+	0xD2,
+	0x88,
+	0xD2,
+	0xA8,
+	0xD2,
+	0xB8,
+	0x7D,
+	0x40,
+	0x7F,
+	0x4F,
+	0x12,
+	0x06,
+	0x63,
+	0xC2,
+	0x0D,
+	0xC2,
+	0x04,
+	0xC2,
+	0x07,
+	0xC2,
+	0x0F,
+	0xC2,
+	0x02,
+	0xE4,
+	0xF5,
+	0x47,
+	0xD2,
+	0x0A,
+	0xD2,
+	0x00,
+	0xD2,
+	0x09,
+	0xD2,
+	0x0C,
+	0xC2,
+	0x05,
+	0xC2,
+	0x08,
+	0xC2,
+	0x0B,
+	0x7E,
+	0x05,
+	0x7F,
+	0x7B,
+	0x12,
+	0x06,
+	0x8A,
+	0x7F,
+	0x0A,
+	0x12,
+	0x0C,
+	0xB4,
+	0x12,
+	0x07,
+	0x69,
+	0x75,
+	0x15,
+	0x19,
+	0x75,
+	0x16,
+	0x19,
+	0x75,
+	0x17,
+	0x0C,
+	0x12,
+	0x0C,
+	0x23,
+	0x7F,
+	0x0A,
+	0x12,
+	0x0C,
+	0x92,
+	0xE5,
+	0x47,
+	0x24,
+	0xFF,
+	0x92,
+	0x05,
+	0x7D,
+	0xC0,
+	0x7F,
+	0x6E,
+	0x12,
+	0x06,
+	0x75,
+	0xAF,
+	0x47,
+	0x12,
+	0x0B,
+	0xF9,
+	0xC2,
+	0x06,
+	0x7D,
+	0x40,
+	0x7F,
+	0x4F,
+	0x12,
+	0x06,
+	0x4E,
+	0x75,
+	0x23,
+	0x00,
+	0x75,
+	0x24,
+	0x01,
+	0xE4,
+	0xF5,
+	0x46,
+	0x12,
+	0x06,
+	0xC6,
+	0x30,
+	0x0D,
+	0x05,
+	0x7F,
+	0xFF,
+	0x12,
+	0x08,
+	0x97,
+	0x30,
+	0x07,
+	0x30,
+	0x20,
+	0x04,
+	0x0C,
+	0x7F,
+	0x25,
+	0x12,
+	0x0C,
+	0x77,
+	0xEF,
+	0x30,
+	0xE4,
+	0x03,
+	0x12,
+	0x00,
+	0x0E,
+	0x7B,
+	0x12,
+	0x7D,
+	0x36,
+	0x7C,
+	0x00,
+	0x7F,
+	0x50,
+	0x12,
+	0x0B,
+	0x9F,
+	0x92,
+	0x10,
+	0x85,
+	0x3A,
+	0x35,
+	0x85,
+	0x25,
+	0x36,
+	0x85,
+	0x28,
+	0x37,
+	0xA2,
+	0x10,
+	0x92,
+	0x13,
+	0x7F,
+	0x0F,
+	0x12,
+	0x0A,
+	0xFF,
+	0xC2,
+	0x07,
+	0xE5,
+	0x16,
+	0x60,
+	0x03,
+	0x02,
+	0x03,
+	0xA3,
+	0x30,
+	0x02,
+	0x2D,
+	0xC2,
+	0xA8,
+	0x7F,
+	0x0A,
+	0x12,
+	0x0C,
+	0x92,
+	0xC2,
+	0x02,
+	0x30,
+	0x05,
+	0x0C,
+	0xE5,
+	0x47,
+	0x60,
+	0x04,
+	0xD2,
+	0x03,
+	0x80,
+	0x0C,
+	0xAF,
+	0x47,
+	0x80,
+	0x05,
+	0xE5,
+	0x47,
+	0x60,
+	0x04,
+	0xFF,
+	0x12,
+	0x0B,
+	0xF9,
+	0xE5,
+	0x47,
+	0x24,
+	0xFF,
+	0x92,
+	0x05,
+	0x75,
+	0x16,
+	0x19,
+	0xD2,
+	0xA8,
+	0x80,
+	0x54,
+	0x20,
+	0x0B,
+	0x1A,
+	0x30,
+	0x05,
+	0x09,
+	0x7F,
+	0x09,
+	0x12,
+	0x0C,
+	0x6F,
+	0xEF,
+	0x13,
+	0x92,
+	0x09,
+	0xD2,
+	0x0C,
+	0x7F,
+	0x08,
+	0x12,
+	0x0C,
+	0x6F,
+	0xEF,
+	0x54,
+	0x0E,
+	0x70,
+	0x02,
+	0xC2,
+	0x0C,
+	0xE5,
+	0x47,
+	0x60,
+	0x22,
+	0x7F,
+	0x09,
+	0x12,
+	0x0C,
+	0x6F,
+	0xEF,
+	0x20,
+	0xE0,
+	0x19,
+	0x7F,
+	0x0A,
+	0x12,
+	0x0C,
+	0x6F,
+	0xEF,
+	0x30,
+	0xE2,
+	0x10,
+	0x7D,
+	0x04,
+	0x7F,
+	0x5C,
+	0x12,
+	0x06,
+	0x6F,
+	0x7D,
+	0x01,
+	0x7F,
+	0x07,
+	0x12,
+	0x06,
+	0x4E,
+	0x80,
+	0x0E,
+	0x7D,
+	0x04,
+	0x7F,
+	0x5C,
+	0x12,
+	0x06,
+	0x5A,
+	0x7D,
+	0x01,
+	0x7F,
+	0x07,
+	0x12,
+	0x06,
+	0x63,
+	0x75,
+	0x16,
+	0x4B,
+	0xE5,
+	0x17,
+	0x70,
+	0x2C,
+	0x7F,
+	0x7F,
+	0x12,
+	0x0C,
+	0x7B,
+	0xEF,
+	0x54,
+	0x04,
+	0xF5,
+	0x49,
+	0x65,
+	0x3D,
+	0x60,
+	0x1B,
+	0x85,
+	0x3D,
+	0x49,
+	0x7F,
+	0x0A,
+	0x12,
+	0x0C,
+	0xB4,
+	0xE5,
+	0x3D,
+	0x65,
+	0x49,
+	0x60,
+	0x0D,
+	0xE5,
+	0x3D,
+	0x70,
+	0x03,
+	0xD3,
+	0x80,
+	0x01,
+	0xC3,
+	0x92,
+	0x11,
+	0x12,
+	0x0B,
+	0xCD,
+	0x75,
+	0x17,
+	0x19,
+	0x05,
+	0x24,
+	0xE5,
+	0x24,
+	0xAE,
+	0x23,
+	0x70,
+	0x02,
+	0x05,
+	0x23,
+	0x14,
+	0x4E,
+	0x60,
+	0x03,
+	0x02,
+	0x02,
+	0xDA,
+	0x75,
+	0x13,
+	0x07,
+	0x75,
+	0x14,
+	0xD0,
+	0x05,
+	0x46,
+	0xE5,
+	0x46,
+	0x20,
+	0xE0,
+	0x03,
+	0x02,
+	0x02,
+	0xDA,
+	0x02,
+	0x02,
+	0xDA,
+	0x02,
+	0x05,
+	0x4B,
+	0xEC,
+	0x5D,
+	0x04,
+	0x60,
+	0x05,
+	0xE8,
+	0x59,
+	0x04,
+	0x70,
+	0x03,
+	0x02,
+	0x05,
+	0x41,
+	0x12,
+	0x05,
+	0x0C,
+	0x58,
+	0x04,
+	0x60,
+	0xF6,
+	0xEC,
+	0x48,
+	0x60,
+	0xF2,
+	0xEC,
+	0x70,
+	0x04,
+	0xFD,
+	0xFE,
+	0xFF,
+	0x22,
+	0xC8,
+	0x60,
+	0xDB,
+	0x24,
+	0x81,
+	0xC8,
+	0x50,
+	0x09,
+	0xC3,
+	0x98,
+	0x60,
+	0x02,
+	0x50,
+	0x06,
+	0x02,
+	0x05,
+	0x48,
+	0x98,
+	0x50,
+	0xCA,
+	0xF5,
+	0x82,
+	0xE9,
+	0x29,
+	0x4B,
+	0x4A,
+	0x70,
+	0x05,
+	0xAB,
+	0x82,
+	0x02,
+	0x05,
+	0x37,
+	0x75,
+	0xF0,
+	0x00,
+	0x7C,
+	0x1A,
+	0x78,
+	0x80,
+	0xC3,
+	0xEF,
+	0x9B,
+	0xEE,
+	0x9A,
+	0xED,
+	0x99,
+	0x40,
+	0x0D,
+	0xC3,
+	0xEF,
+	0x9B,
+	0xFF,
+	0xEE,
+	0x9A,
+	0xFE,
+	0xED,
+	0x99,
+	0xFD,
+	0xE8,
+	0x42,
+	0xF0,
+	0xDC,
+	0x23,
+	0xAC,
+	0xF0,
+	0xD0,
+	0xE0,
+	0xFF,
+	0xD0,
+	0xE0,
+	0xFE,
+	0xD0,
+	0xE0,
+	0xFD,
+	0xAB,
+	0x82,
+	0x20,
+	0xE7,
+	0x10,
+	0x1B,
+	0xEB,
+	0x60,
+	0xBA,
+	0xEC,
+	0x2C,
+	0xFC,
+	0xEF,
+	0x33,
+	0xFF,
+	0xEE,
+	0x33,
+	0xFE,
+	0xED,
+	0x33,
+	0xFD,
+	0x02,
+	0x05,
+	0x23,
+	0xE8,
+	0x03,
+	0xF8,
+	0x30,
+	0xE7,
+	0x05,
+	0xC0,
+	0xF0,
+	0x75,
+	0xF0,
+	0x00,
+	0xEF,
+	0x2F,
+	0xFF,
+	0xEE,
+	0x33,
+	0xFE,
+	0xED,
+	0x33,
+	0xFD,
+	0x40,
+	0xB8,
+	0x30,
+	0xE7,
+	0xC2,
+	0x80,
+	0xAA,
+	0x75,
+	0xF0,
+	0x20,
+	0x80,
+	0x0E,
+	0x75,
+	0xF0,
+	0x10,
+	0x80,
+	0x05,
+	0x75,
+	0xF0,
+	0x08,
+	0x7D,
+	0x00,
+	0x7E,
+	0x00,
+	0x7F,
+	0x00,
+	0x33,
+	0x92,
+	0xD5,
+	0x30,
+	0xD5,
+	0x03,
+	0x12,
+	0x05,
+	0x56,
+	0xEC,
+	0x33,
+	0x40,
+	0x10,
+	0xEF,
+	0x33,
+	0xFF,
+	0xEE,
+	0x33,
+	0xFE,
+	0xED,
+	0x33,
+	0xFD,
+	0xEC,
+	0x33,
+	0xFC,
+	0xD5,
+	0xF0,
+	0xED,
+	0x22,
+	0xE5,
+	0xF0,
+	0x24,
+	0x7E,
+	0xA2,
+	0xD5,
+	0x13,
+	0xCC,
+	0x92,
+	0xE7,
+	0xCD,
+	0xCE,
+	0xFF,
+	0x22,
+	0xED,
+	0xD2,
+	0xE7,
+	0xCD,
+	0x33,
+	0xEC,
+	0x33,
+	0x92,
+	0xD5,
+	0x24,
+	0x81,
+	0x40,
+	0x06,
+	0xE4,
+	0xFF,
+	0xFE,
+	0xFD,
+	0xFC,
+	0x22,
+	0xFC,
+	0xE4,
+	0xCF,
+	0xCE,
+	0xCD,
+	0xCC,
+	0x24,
+	0xE0,
+	0x50,
+	0x11,
+	0x74,
+	0xFF,
+	0x80,
+	0xED,
+	0xC3,
+	0xCC,
+	0x13,
+	0xCC,
+	0xCD,
+	0x13,
+	0xCD,
+	0xCE,
+	0x13,
+	0xCE,
+	0xCF,
+	0x13,
+	0xCF,
+	0x04,
+	0x70,
+	0xF0,
+	0x30,
+	0xD5,
+	0xDE,
+	0x02,
+	0x05,
+	0x56,
+	0xE9,
+	0xD2,
+	0xE7,
+	0xC9,
+	0x33,
+	0xE8,
+	0x33,
+	0xF8,
+	0x92,
+	0xD5,
+	0xED,
+	0xD2,
+	0xE7,
+	0xCD,
+	0x33,
+	0xEC,
+	0x33,
+	0xFC,
+	0x50,
+	0x02,
+	0xB2,
+	0xD5,
+	0x22,
+	0xEC,
+	0x30,
+	0xE7,
+	0x10,
+	0x0F,
+	0xBF,
+	0x00,
+	0x0C,
+	0x0E,
+	0xBE,
+	0x00,
+	0x08,
+	0x0D,
+	0xBD,
+	0x00,
+	0x04,
+	0x0B,
+	0xEB,
+	0x60,
+	0x14,
+	0xA2,
+	0xD5,
+	0xEB,
+	0x13,
+	0xFC,
+	0xED,
+	0x92,
+	0xE7,
+	0xFD,
+	0x22,
+	0x74,
+	0xFF,
+	0xFC,
+	0xFD,
+	0xFE,
+	0xFF,
+	0x22,
+	0xE4,
+	0x80,
+	0xF8,
+	0xA2,
+	0xD5,
+	0x74,
+	0xFF,
+	0x13,
+	0xFC,
+	0x7D,
+	0x80,
+	0xE4,
+	0x80,
+	0xEF,
+	0xC3,
+	0xE4,
+	0x9F,
+	0xFF,
+	0xE4,
+	0x9E,
+	0xFE,
+	0xE4,
+	0x9D,
+	0xFD,
+	0xE4,
+	0x9C,
+	0xFC,
+	0x22,
+	0x26,
+	0x27,
+	0x42,
+	0x43,
+	0x44,
+	0x45,
+	0x46,
+	0x47,
+	0x6A,
+	0x51,
+	0x52,
+	0x53,
+	0x57,
+	0x58,
+	0x59,
+	0x5A,
+	0x07,
+	0x01,
+	0x2B,
+	0x00,
+	0x00,
+	0x01,
+	0x00,
+	0x14,
+	0x5A,
+	0x00,
+	0x20,
+	0x07,
+	0x10,
+	0x11,
+	0x0E,
+	0x80,
+	0x14,
+	0x59,
+	0xE0,
+	0x24,
+	0x59,
+	0x60,
+	0x10,
+	0x19,
+	0x04,
+	0x00,
+	0x1C,
+	0x69,
+	0x00,
+	0x1D,
+	0x78,
+	0x04,
+	0x76,
+	0x00,
+	0x04,
+	0x77,
+	0x20,
+	0x04,
+	0x75,
+	0x08,
+	0x14,
+	0x52,
+	0x10,
+	0x23,
+	0x10,
+	0x01,
+	0x13,
+	0x0F,
+	0x20,
+	0xF0,
+	0x10,
+	0x80,
+	0x1F,
+	0x40,
+	0x04,
+	0x20,
+	0x13,
+	0x10,
+	0x05,
+	0x08,
+	0x14,
+	0x04,
+	0x03,
+	0x02,
+	0x02,
+	0x02,
+	0x12,
+	0x01,
+	0x11,
+	0x01,
+	0x00,
+	0x50,
+	0x00,
+	0x40,
+	0x04,
+	0x66,
+	0x50,
+	0x00,
+	0x30,
+	0x08,
+	0x40,
+	0x60,
+	0xB0,
+	0x40,
+	0x10,
+	0x20,
+	0x09,
+	0x01,
+	0x20,
+	0x08,
+	0xF0,
+	0x20,
+	0x07,
+	0x19,
+	0x21,
+	0x0D,
+	0x80,
+	0x21,
+	0x16,
+	0x01,
+	0xF0,
+	0x10,
+	0x08,
+	0x0E,
+	0x10,
+	0x09,
+	0x04,
+	0xF0,
+	0x20,
+	0x08,
+	0x0E,
+	0x20,
+	0x09,
+	0x04,
+	0xF0,
+	0x20,
+	0x09,
+	0x5D,
+	0x20,
+	0x08,
+	0xFE,
+	0x20,
+	0x07,
+	0x1D,
+	0x20,
+	0x0A,
+	0x20,
+	0x20,
+	0x07,
+	0x02,
+	0x24,
+	0x54,
+	0x10,
+	0x21,
+	0x11,
+	0x80,
+	0x10,
+	0x0A,
+	0x04,
+	0xF0,
+	0x11,
+	0x11,
+	0x80,
+	0x10,
+	0x07,
+	0x02,
+	0x14,
+	0x54,
+	0x10,
+	0x10,
+	0x07,
+	0x1D,
+	0x10,
+	0x0A,
+	0x20,
+	0x11,
+	0x16,
+	0x01,
+	0x11,
+	0x0D,
+	0x80,
+	0x10,
+	0x08,
+	0xF0,
+	0x10,
+	0x09,
+	0x5D,
+	0x14,
+	0x52,
+	0x01,
+	0x24,
+	0x52,
+	0x01,
+	0xF0,
+	0x7B,
+	0x00,
+	0x80,
+	0x0A,
+	0x7B,
+	0x01,
+	0x80,
+	0x06,
+	0x7B,
+	0x03,
+	0x80,
+	0x02,
+	0x7B,
+	0x04,
+	0x7C,
+	0x00,
+	0x80,
+	0x00,
+	0x12,
+	0x06,
+	0x42,
+	0xE2,
+	0x5C,
+	0x4D,
+	0xF2,
+	0x78,
+	0x03,
+	0xEB,
+	0xF2,
+	0xD2,
+	0xAF,
+	0x22,
+	0xC2,
+	0xAF,
+	0x78,
+	0x83,
+	0xE2,
+	0xCB,
+	0xF2,
+	0x74,
+	0x80,
+	0x2F,
+	0xF8,
+	0x22,
+	0x7B,
+	0x00,
+	0x80,
+	0x0A,
+	0x7B,
+	0x01,
+	0x80,
+	0x06,
+	0x7B,
+	0x03,
+	0x80,
+	0x02,
+	0x7B,
+	0x04,
+	0xED,
+	0xF4,
+	0xFC,
+	0x7D,
+	0x00,
+	0x80,
+	0xD1,
+	0x7B,
+	0x00,
+	0x80,
+	0x0A,
+	0x7B,
+	0x01,
+	0x80,
+	0x06,
+	0x7B,
+	0x03,
+	0x80,
+	0x02,
+	0x7B,
+	0x04,
+	0x7C,
+	0xFF,
+	0x80,
+	0xBF,
+	0x7B,
+	0x03,
+	0x80,
+	0x02,
+	0x7B,
+	0x04,
+	0x12,
+	0x06,
+	0x42,
+	0xED,
+	0xF4,
+	0xFF,
+	0xE2,
+	0x5F,
+	0xF2,
+	0x4D,
+	0xF2,
+	0x5F,
+	0xF2,
+	0x80,
+	0xB1,
+	0x8E,
+	0x83,
+	0x8F,
+	0x82,
+	0xE4,
+	0x93,
+	0xA3,
+	0xFB,
+	0x54,
+	0x0F,
+	0xCB,
+	0x54,
+	0xF0,
+	0xB4,
+	0xF0,
+	0x01,
+	0x22,
+	0xFD,
+	0xE4,
+	0x93,
+	0xA3,
+	0xFF,
+	0xE4,
+	0x93,
+	0xA3,
+	0xCD,
+	0xB4,
+	0x00,
+	0x05,
+	0x12,
+	0x06,
+	0x30,
+	0x80,
+	0xE2,
+	0xB4,
+	0x10,
+	0x05,
+	0x12,
+	0x06,
+	0x5C,
+	0x80,
+	0xDA,
+	0xB4,
+	0x20,
+	0x05,
+	0x12,
+	0x06,
+	0x71,
+	0x80,
+	0xD2,
+	0xB4,
+	0x30,
+	0x05,
+	0x12,
+	0x06,
+	0x7B,
+	0x80,
+	0xCA,
+	0x80,
+	0xC8,
+	0xD2,
+	0x11,
+	0xD2,
+	0x12,
+	0x30,
+	0x06,
+	0x03,
+	0x02,
+	0x07,
+	0x66,
+	0x7F,
+	0x4F,
+	0x12,
+	0x0C,
+	0x6F,
+	0x8F,
+	0x4A,
+	0xE5,
+	0x4A,
+	0x20,
+	0xE6,
+	0x03,
+	0x02,
+	0x07,
+	0x66,
+	0xD2,
+	0x06,
+	0x53,
+	0x4A,
+	0x3F,
+	0xE5,
+	0x4A,
+	0x24,
+	0xFD,
+	0x60,
+	0x12,
+	0x24,
+	0xFD,
+	0x60,
+	0x14,
+	0x24,
+	0xE7,
+	0x60,
+	0x2E,
+	0x24,
+	0x1E,
+	0x70,
+	0x5F,
+	0xD2,
+	0x0D,
+	0xC2,
+	0x11,
+	0x80,
+	0x5E,
+	0xD2,
+	0x07,
+	0xC2,
+	0x11,
+	0x80,
+	0x58,
+	0x30,
+	0x0A,
+	0x04,
+	0x7F,
+	0x80,
+	0x80,
+	0x02,
+	0x7F,
+	0x00,
+	0x8F,
+	0x29,
+	0x7F,
+	0x25,
+	0x12,
+	0x0C,
+	0x77,
+	0xEF,
+	0x30,
+	0xE4,
+	0x03,
+	0x43,
+	0x29,
+	0x01,
+	0xC2,
+	0x0A,
+	0x75,
+	0x4A,
+	0x01,
+	0x80,
+	0x3A,
+	0x75,
+	0x4B,
+	0x05,
+	0x75,
+	0x4C,
+	0x74,
+	0xE4,
+	0xFF,
+	0xE5,
+	0x4C,
+	0x2F,
+	0xF5,
+	0x82,
+	0xE4,
+	0x35,
+	0x4B,
+	0xF5,
+	0x83,
+	0xE4,
+	0x93,
+	0xFE,
+	0x74,
+	0x29,
+	0x2F,
+	0xF8,
+	0xA6,
+	0x06,
+	0x0F,
+	0xBF,
+	0x07,
+	0xE9,
+	0x7F,
+	0x50,
+	0x12,
+	0x0C,
+	0x7B,
+	0x8F,
+	0x2C,
+	0x7F,
+	0x51,
+	0x12,
+	0x0C,
+	0x7B,
+	0xEF,
+	0x54,
+	0x0F,
+	0xF5,
+	0x2D,
+	0x75,
+	0x4A,
+	0x07,
+	0x80,
+	0x05,
+	0xE4,
+	0xF5,
+	0x4A,
+	0xC2,
+	0x12,
+	0x30,
+	0x11,
+	0x09,
+	0xA2,
+	0x12,
+	0x92,
+	0x13,
+	0xAF,
+	0x4A,
+	0x12,
+	0x0A,
+	0xFF,
+	0xA2,
+	0x06,
+	0x22,
+	0xC2,
+	0x96,
+	0xD2,
+	0x97,
+	0xD2,
+	0x96,
+	0x22,
+	0x22,
+	0xC2,
+	0x97,
+	0xD2,
+	0x96,
+	0x74,
+	0x28,
+	0x00,
+	0x00,
+	0xD5,
+	0xE0,
+	0xFB,
+	0xD2,
+	0x97,
+	0x74,
+	0x1E,
+	0x00,
+	0x00,
+	0xD5,
+	0xE0,
+	0xFB,
+	0x22,
+	0xC2,
+	0x97,
+	0xD2,
+	0x97,
+	0x74,
+	0x1E,
+	0x00,
+	0x00,
+	0xD5,
+	0xE0,
+	0xFB,
+	0xD2,
+	0x96,
+	0x74,
+	0x28,
+	0x00,
+	0x00,
+	0xD5,
+	0xE0,
+	0xFB,
+	0x22,
+	0xD2,
+	0x97,
+	0xD2,
+	0x96,
+	0x74,
+	0x28,
+	0x00,
+	0x00,
+	0xD5,
+	0xE0,
+	0xFB,
+	0xC2,
+	0x97,
+	0x74,
+	0x1E,
+	0x00,
+	0x00,
+	0xD5,
+	0xE0,
+	0xFB,
+	0xC2,
+	0x96,
+	0x74,
+	0x1E,
+	0x00,
+	0x00,
+	0xD5,
+	0xE0,
+	0xFB,
+	0x22,
+	0xEF,
+	0x7E,
+	0x08,
+	0x33,
+	0xC0,
+	0xE0,
+	0x40,
+	0x04,
+	0xC2,
+	0x97,
+	0x80,
+	0x02,
+	0xD2,
+	0x97,
+	0x74,
+	0x11,
+	0x00,
+	0x00,
+	0xD5,
+	0xE0,
+	0xFB,
+	0xD2,
+	0x96,
+	0x74,
+	0x11,
+	0x00,
+	0x00,
+	0xD5,
+	0xE0,
+	0xFB,
+	0xC2,
+	0x96,
+	0x74,
+	0x11,
+	0x00,
+	0x00,
+	0xD5,
+	0xE0,
+	0xFB,
+	0xD0,
+	0xE0,
+	0xDE,
+	0xD8,
+	0xD2,
+	0x97,
+	0x74,
+	0x11,
+	0x00,
+	0x00,
+	0xD5,
+	0xE0,
+	0xFB,
+	0xD2,
+	0x96,
+	0x74,
+	0x11,
+	0x00,
+	0x00,
+	0xD5,
+	0xE0,
+	0xFB,
+	0xA2,
+	0x97,
+	0xE4,
+	0x92,
+	0xE0,
+	0xFE,
+	0xC2,
+	0x96,
+	0x74,
+	0x11,
+	0x00,
+	0x00,
+	0xD5,
+	0xE0,
+	0xFB,
+	0xEE,
+	0x22,
+	0x8F,
+	0x5E,
+	0x8D,
+	0x5F,
+	0x7F,
+	0x5A,
+	0x12,
+	0x0C,
+	0x7B,
+	0xEF,
+	0x54,
+	0x80,
+	0xF5,
+	0x62,
+	0xE5,
+	0x5E,
+	0xB4,
+	0x01,
+	0x04,
+	0x7F,
+	0x40,
+	0x80,
+	0x02,
+	0x7F,
+	0x00,
+	0x8F,
+	0x60,
+	0x43,
+	0x60,
+	0x80,
+	0xAD,
+	0x60,
+	0x7F,
+	0x0A,
+	0x12,
+	0x06,
+	0x2E,
+	0xE5,
+	0x60,
+	0x44,
+	0x20,
+	0xFD,
+	0x7F,
+	0x0A,
+	0x12,
+	0x06,
+	0x2E,
+	0xAD,
+	0x60,
+	0x7F,
+	0x0A,
+	0x12,
+	0x06,
+	0x2E,
+	0x7F,
+	0x0E,
+	0x12,
+	0x0C,
+	0x7B,
+	0xEF,
+	0x20,
+	0xE7,
+	0x4E,
+	0x7F,
+	0x5A,
+	0x12,
+	0x0C,
+	0x7B,
+	0xEF,
+	0x54,
+	0x80,
+	0x65,
+	0x62,
+	0x60,
+	0x03,
+	0x7F,
+	0xFF,
+	0x22,
+	0x7F,
+	0x0E,
+	0x12,
+	0x0C,
+	0x7B,
+	0xEF,
+	0x30,
+	0xE6,
+	0x03,
+	0x7F,
+	0x01,
+	0x22,
+	0x85,
+	0x60,
+	0x61,
+	0x7F,
+	0x0C,
+	0x12,
+	0x0C,
+	0x7B,
+	0x8F,
+	0x60,
+	0xE5,
+	0x61,
+	0x65,
+	0x60,
+	0x60,
+	0x04,
+	0x7F,
+	0x01,
+	0x80,
+	0x02,
+	0x7F,
+	0x00,
+	0xE5,
+	0x60,
+	0x60,
+	0x04,
+	0x7E,
+	0x01,
+	0x80,
+	0x02,
+	0x7E,
+	0x00,
+	0xEE,
+	0x5F,
+	0x60,
+	0xB8,
+	0x7F,
+	0x0D,
+	0x12,
+	0x0C,
+	0x7B,
+	0xE5,
+	0x60,
+	0x14,
+	0x25,
+	0x5F,
+	0xF8,
+	0xA6,
+	0x07,
+	0x80,
+	0xA9,
+	0x7F,
+	0x00,
+	0x22,
+	0xAD,
+	0x07,
+	0x8D,
+	0x4A,
+	0xBD,
+	0xFF,
+	0x07,
+	0x7F,
+	0x50,
+	0x12,
+	0x0C,
+	0x6F,
+	0xAD,
+	0x07,
+	0xED,
+	0x54,
+	0x80,
+	0xFF,
+	0x53,
+	0x05,
+	0x7F,
+	0xED,
+	0xC4,
+	0x54,
+	0x0F,
+	0xFE,
+	0xED,
+	0x54,
+	0x0F,
+	0xC4,
+	0x54,
+	0xF0,
+	0xFD,
+	0xEF,
+	0x4E,
+	0xFF,
+	0x7B,
+	0x10,
+	0x12,
+	0x09,
+	0x15,
+	0x92,
+	0x11,
+	0xAD,
+	0x4A,
+	0x7F,
+	0x66,
+	0xE4,
+	0xF5,
+	0x4A,
+	0x30,
+	0x11,
+	0x08,
+	0xEF,
+	0x25,
+	0x4A,
+	0xF8,
+	0xE6,
+	0xFE,
+	0x80,
+	0x02,
+	0x7E,
+	0x00,
+	0x74,
+	0x29,
+	0x25,
+	0x4A,
+	0xF8,
+	0xA6,
+	0x06,
+	0x05,
+	0x4A,
+	0xE5,
+	0x4A,
+	0xB4,
+	0x10,
+	0xE5,
+	0xED,
+	0xF4,
+	0x70,
+	0x25,
+	0xA2,
+	0x11,
+	0x92,
+	0x13,
+	0x7F,
+	0x10,
+	0x12,
+	0x0A,
+	0xFF,
+	0xC2,
+	0x0D,
+	0x7D,
+	0x40,
+	0x7F,
+	0x4F,
+	0x12,
+	0x06,
+	0x4E,
+	0x30,
+	0x11,
+	0x09,
+	0x7D,
+	0x80,
+	0x7F,
+	0x50,
+	0x12,
+	0x06,
+	0x4E,
+	0x80,
+	0x07,
+	0x7D,
+	0x40,
+	0x7F,
+	0x50,
+	0x12,
+	0x06,
+	0x63,
+	0xA2,
+	0x11,
+	0x22,
+	0x25,
+	0x51,
+	0xFD,
+	0xAF,
+	0x4E,
+	0x8F,
+	0x59,
+	0x8D,
+	0x5A,
+	0x8B,
+	0x5B,
+	0x75,
+	0x5C,
+	0x03,
+	0xE5,
+	0x59,
+	0x30,
+	0xE7,
+	0x04,
+	0x7F,
+	0x01,
+	0x80,
+	0x02,
+	0x7F,
+	0x00,
+	0x8F,
+	0x5D,
+	0x53,
+	0x59,
+	0x7F,
+	0xAF,
+	0x5C,
+	0x15,
+	0x5C,
+	0xEF,
+	0x60,
+	0x4C,
+	0xE5,
+	0x5D,
+	0x70,
+	0x1D,
+	0xE5,
+	0x59,
+	0xD3,
+	0x94,
+	0x00,
+	0x40,
+	0x16,
+	0x12,
+	0x07,
+	0x70,
+	0x12,
+	0x07,
+	0x9B,
+	0x7F,
+	0x60,
+	0x12,
+	0x07,
+	0xB9,
+	0xAF,
+	0x59,
+	0x12,
+	0x07,
+	0xB9,
+	0x12,
+	0x07,
+	0x86,
+	0x12,
+	0x07,
+	0x70,
+	0xE5,
+	0x5D,
+	0x60,
+	0x0D,
+	0xE5,
+	0x5A,
+	0xFD,
+	0x7C,
+	0x00,
+	0xAB,
+	0x5B,
+	0x7F,
+	0x50,
+	0x7E,
+	0x02,
+	0x80,
+	0x0B,
+	0xE5,
+	0x5A,
+	0xFD,
+	0x7C,
+	0x00,
+	0xAB,
+	0x5B,
+	0x7F,
+	0x50,
+	0x7E,
+	0x00,
+	0x12,
+	0x0A,
+	0x61,
+	0x7D,
+	0x66,
+	0xE4,
+	0xFF,
+	0x12,
+	0x08,
+	0x07,
+	0xEF,
+	0x70,
+	0xAF,
+	0xD3,
+	0x22,
+	0xC3,
+	0x22,
+	0xC0,
+	0xE0,
+	0xC0,
+	0xD0,
+	0xC2,
+	0x8C,
+	0x75,
+	0x8A,
+	0x40,
+	0x75,
+	0x8C,
+	0x7C,
+	0xD2,
+	0x8C,
+	0x05,
+	0x18,
+	0xE5,
+	0x18,
+	0x70,
+	0x19,
+	0x05,
+	0x10,
+	0xE5,
+	0x10,
+	0xD3,
+	0x94,
+	0x02,
+	0x40,
+	0x05,
+	0x75,
+	0x10,
+	0x00,
+	0xD2,
+	0x0E,
+	0xE5,
+	0x10,
+	0xB4,
+	0x01,
+	0x03,
+	0xD3,
+	0x80,
+	0x01,
+	0xC3,
+	0x92,
+	0x03,
+	0xE5,
+	0x11,
+	0x60,
+	0x02,
+	0x15,
+	0x11,
+	0xE5,
+	0x12,
+	0x60,
+	0x02,
+	0x15,
+	0x12,
+	0xE5,
+	0x15,
+	0x60,
+	0x02,
+	0x15,
+	0x15,
+	0xE5,
+	0x16,
+	0x60,
+	0x02,
+	0x15,
+	0x16,
+	0xE5,
+	0x17,
+	0x60,
+	0x02,
+	0x15,
+	0x17,
+	0xE5,
+	0x14,
+	0x45,
+	0x13,
+	0x60,
+	0x0A,
+	0xE5,
+	0x14,
+	0x15,
+	0x14,
+	0x70,
+	0x0C,
+	0x15,
+	0x13,
+	0x80,
+	0x08,
+	0xC2,
+	0xAF,
+	0x12,
+	0x0C,
+	0x91,
+	0x02,
+	0x00,
+	0x00,
+	0x74,
+	0x81,
+	0xB5,
+	0x81,
+	0x00,
+	0x40,
+	0x02,
+	0x80,
+	0xEF,
+	0xD0,
+	0xD0,
+	0xD0,
+	0xE0,
+	0x32,
+	0x8F,
+	0x55,
+	0x75,
+	0x58,
+	0x66,
+	0xE4,
+	0xF5,
+	0x56,
+	0xE5,
+	0x55,
+	0xC3,
+	0x13,
+	0xFF,
+	0xE5,
+	0x55,
+	0x30,
+	0xE0,
+	0x04,
+	0x7D,
+	0x80,
+	0x80,
+	0x02,
+	0x7D,
+	0x00,
+	0x7B,
+	0x40,
+	0x12,
+	0x09,
+	0x15,
+	0x40,
+	0x01,
+	0x22,
+	0xE4,
+	0xF5,
+	0x57,
+	0xE5,
+	0x58,
+	0x25,
+	0x57,
+	0xF8,
+	0xE6,
+	0x25,
+	0x56,
+	0xF5,
+	0x56,
+	0x05,
+	0x57,
+	0xE5,
+	0x57,
+	0xB4,
+	0x40,
+	0xEF,
+	0xE5,
+	0x55,
+	0xC3,
+	0x13,
+	0xFF,
+	0xE5,
+	0x55,
+	0x30,
+	0xE0,
+	0x04,
+	0x7E,
+	0x80,
+	0x80,
+	0x02,
+	0x7E,
+	0x00,
+	0xEE,
+	0x24,
+	0x40,
+	0xFD,
+	0x7B,
+	0x40,
+	0x12,
+	0x09,
+	0x15,
+	0x40,
+	0x01,
+	0x22,
+	0xE4,
+	0xF5,
+	0x57,
+	0xE5,
+	0x58,
+	0x25,
+	0x57,
+	0xF8,
+	0xE6,
+	0x25,
+	0x56,
+	0xF5,
+	0x56,
+	0x05,
+	0x57,
+	0xE5,
+	0x57,
+	0xB4,
+	0x40,
+	0xEF,
+	0xE5,
+	0x56,
+	0x70,
+	0x03,
+	0xD3,
+	0x80,
+	0x01,
+	0xC3,
+	0x22,
+	0x8E,
+	0x5E,
+	0x8F,
+	0x5F,
+	0x8C,
+	0x60,
+	0x8D,
+	0x61,
+	0x8B,
+	0x62,
+	0xE5,
+	0x5E,
+	0xF5,
+	0x63,
+	0xEF,
+	0xF5,
+	0x64,
+	0xE5,
+	0x63,
+	0x7D,
+	0x80,
+	0x7F,
+	0x5A,
+	0x30,
+	0xE1,
+	0x05,
+	0x12,
+	0x06,
+	0x6F,
+	0x80,
+	0x03,
+	0x12,
+	0x06,
+	0x5A,
+	0x53,
+	0x63,
+	0x01,
+	0xE5,
+	0x63,
+	0x70,
+	0x0B,
+	0xE5,
+	0x60,
+	0x25,
+	0x64,
+	0xF5,
+	0x64,
+	0xE4,
+	0xF5,
+	0x65,
+	0x80,
+	0x04,
+	0xE5,
+	0x60,
+	0xF5,
+	0x65,
+	0xAD,
+	0x64,
+	0x7F,
+	0x28,
+	0x12,
+	0x06,
+	0x2E,
+	0xAD,
+	0x65,
+	0x7F,
+	0x40,
+	0x12,
+	0x06,
+	0x2E,
+	0xE5,
+	0x61,
+	0xF5,
+	0x65,
+	0xAD,
+	0x65,
+	0x7F,
+	0x29,
+	0x12,
+	0x06,
+	0x2E,
+	0xAD,
+	0x62,
+	0x7F,
+	0x08,
+	0x12,
+	0x06,
+	0x2E,
+	0xAF,
+	0x63,
+	0x22,
+	0xC0,
+	0xE0,
+	0xC0,
+	0xF0,
+	0xC0,
+	0x83,
+	0xC0,
+	0x82,
+	0xC0,
+	0xD0,
+	0x75,
+	0xD0,
+	0x08,
+	0x7F,
+	0x25,
+	0x12,
+	0x0C,
+	0x77,
+	0xEF,
+	0x54,
+	0x10,
+	0xF5,
+	0x48,
+	0x7D,
+	0x40,
+	0x7F,
+	0x6E,
+	0x12,
+	0x06,
+	0x75,
+	0x30,
+	0x00,
+	0x17,
+	0xE5,
+	0x48,
+	0x65,
+	0x47,
+	0x60,
+	0x11,
+	0x85,
+	0x48,
+	0x47,
+	0xD2,
+	0x02,
+	0xD2,
+	0x0A,
+	0xE5,
+	0x16,
+	0xD3,
+	0x94,
+	0x03,
+	0x40,
+	0x03,
+	0x75,
+	0x16,
+	0x03,
+	0xD0,
+	0xD0,
+	0xD0,
+	0x82,
+	0xD0,
+	0x83,
+	0xD0,
+	0xF0,
+	0xD0,
+	0xE0,
+	0x32,
+	0x8F,
+	0x4D,
+	0xE4,
+	0xF5,
+	0x4E,
+	0xE5,
+	0x4E,
+	0xC3,
+	0x95,
+	0x4D,
+	0x50,
+	0x15,
+	0xE5,
+	0x4E,
+	0x90,
+	0x05,
+	0x64,
+	0x93,
+	0xFF,
+	0x74,
+	0x29,
+	0x25,
+	0x4E,
+	0xF8,
+	0xE6,
+	0xFD,
+	0x12,
+	0x06,
+	0x26,
+	0x05,
+	0x4E,
+	0x80,
+	0xE4,
+	0x20,
+	0x13,
+	0x03,
+	0x43,
+	0x4D,
+	0x80,
+	0xAD,
+	0x4D,
+	0x7F,
+	0x50,
+	0x12,
+	0x06,
+	0x22,
+	0x7D,
+	0x40,
+	0x7F,
+	0x4F,
+	0x12,
+	0x06,
+	0x4E,
+	0xC2,
+	0x06,
+	0x22,
+	0x20,
+	0x12,
+	0x15,
+	0x7D,
+	0x08,
+	0x7F,
+	0x0A,
+	0x12,
+	0x06,
+	0x63,
+	0x7D,
+	0xFC,
+	0x7F,
+	0x63,
+	0x12,
+	0x06,
+	0x6F,
+	0x7D,
+	0x01,
+	0x7F,
+	0x64,
+	0x12,
+	0x06,
+	0x6F,
+	0x7D,
+	0x02,
+	0x7F,
+	0x66,
+	0x12,
+	0x06,
+	0x6F,
+	0x7D,
+	0x10,
+	0x7F,
+	0x11,
+	0x12,
+	0x06,
+	0x67,
+	0x7D,
+	0x10,
+	0x7F,
+	0x1A,
+	0x12,
+	0x06,
+	0x67,
+	0x7D,
+	0x08,
+	0x7F,
+	0x16,
+	0x02,
+	0x06,
+	0x67,
+	0x20,
+	0x12,
+	0x15,
+	0x7D,
+	0x08,
+	0x7F,
+	0x0A,
+	0x12,
+	0x06,
+	0x4E,
+	0x7D,
+	0xFC,
+	0x7F,
+	0x63,
+	0x12,
+	0x06,
+	0x5A,
+	0x7D,
+	0x01,
+	0x7F,
+	0x64,
+	0x12,
+	0x06,
+	0x5A,
+	0x7D,
+	0x02,
+	0x7F,
+	0x66,
+	0x12,
+	0x06,
+	0x5A,
+	0x7D,
+	0x10,
+	0x7F,
+	0x11,
+	0x12,
+	0x06,
+	0x52,
+	0x7D,
+	0x10,
+	0x7F,
+	0x1A,
+	0x12,
+	0x06,
+	0x52,
+	0x7D,
+	0x08,
+	0x7F,
+	0x16,
+	0x02,
+	0x06,
+	0x52,
+	0x8F,
+	0x4A,
+	0x8C,
+	0x4B,
+	0x8D,
+	0x4C,
+	0x8B,
+	0x4D,
+	0xE4,
+	0xF5,
+	0x4E,
+	0xAF,
+	0x4A,
+	0x7E,
+	0x00,
+	0xAB,
+	0x4D,
+	0xAD,
+	0x4C,
+	0xAC,
+	0x4B,
+	0x12,
+	0x0A,
+	0x61,
+	0x7D,
+	0x29,
+	0xE4,
+	0xFF,
+	0x12,
+	0x08,
+	0x07,
+	0xEF,
+	0x70,
+	0x02,
+	0xD3,
+	0x22,
+	0x05,
+	0x4E,
+	0xE5,
+	0x4E,
+	0xD3,
+	0x94,
+	0x02,
+	0x40,
+	0xDE,
+	0x22,
+	0xA2,
+	0x11,
+	0x92,
+	0x0B,
+	0x30,
+	0x11,
+	0x0F,
+	0x12,
+	0x0C,
+	0x49,
+	0x7E,
+	0x05,
+	0x7F,
+	0xE0,
+	0x12,
+	0x06,
+	0x8A,
+	0xD2,
+	0x12,
+	0x02,
+	0x0B,
+	0x37,
+	0xD2,
+	0x12,
+	0x12,
+	0x0B,
+	0x6B,
+	0x20,
+	0x09,
+	0x03,
+	0x12,
+	0x0C,
+	0xD6,
+	0x20,
+	0x0C,
+	0x07,
+	0x7E,
+	0x05,
+	0x7F,
+	0xD9,
+	0x12,
+	0x06,
+	0x8A,
+	0x22,
+	0xC2,
+	0x04,
+	0xEF,
+	0x60,
+	0x1A,
+	0x7D,
+	0x80,
+	0x7F,
+	0x0E,
+	0x12,
+	0x06,
+	0x52,
+	0x7F,
+	0x64,
+	0x7E,
+	0x00,
+	0x12,
+	0x0C,
+	0xF8,
+	0x12,
+	0x00,
+	0x0E,
+	0x20,
+	0x09,
+	0x03,
+	0x12,
+	0x0C,
+	0xD6,
+	0xD2,
+	0x03,
+	0x22,
+	0x12,
+	0x0C,
+	0x49,
+	0x7D,
+	0x80,
+	0x7F,
+	0x0E,
+	0x12,
+	0x06,
+	0x67,
+	0x22,
+	0xC2,
+	0xAF,
+	0xE4,
+	0xF5,
+	0x11,
+	0xF5,
+	0x12,
+	0x75,
+	0x13,
+	0x07,
+	0x75,
+	0x14,
+	0xD0,
+	0xF5,
+	0x18,
+	0xF5,
+	0x10,
+	0xC2,
+	0x8C,
+	0x53,
+	0x89,
+	0xF0,
+	0x43,
+	0x89,
+	0x01,
+	0x75,
+	0x8A,
+	0x40,
+	0x75,
+	0x8C,
+	0x7C,
+	0xD2,
+	0xA9,
+	0xD2,
+	0x8C,
+	0xD2,
+	0xAF,
+	0x22,
+	0x7E,
+	0x05,
+	0x7F,
+	0xC9,
+	0x12,
+	0x06,
+	0x8A,
+	0x7F,
+	0x08,
+	0x12,
+	0x0C,
+	0x6F,
+	0xEF,
+	0x54,
+	0x0E,
+	0x60,
+	0x07,
+	0x7E,
+	0x05,
+	0x7F,
+	0xE0,
+	0x12,
+	0x06,
+	0x8A,
+	0x7D,
+	0x04,
+	0x7F,
+	0x5C,
+	0x12,
+	0x06,
+	0x5A,
+	0x7D,
+	0x01,
+	0x7F,
+	0x07,
+	0x02,
+	0x06,
+	0x63,
+	0x7D,
+	0x00,
+	0x80,
+	0x0A,
+	0x7D,
+	0x01,
+	0x80,
+	0x06,
+	0x7D,
+	0x03,
+	0x80,
+	0x02,
+	0x7D,
+	0x04,
+	0xC2,
+	0xAF,
+	0x78,
+	0x83,
+	0xE2,
+	0xCD,
+	0xF2,
+	0x74,
+	0x80,
+	0x2F,
+	0xF8,
+	0xE2,
+	0x78,
+	0x03,
+	0xFF,
+	0xED,
+	0xF2,
+	0xD2,
+	0xAF,
+	0x22,
+	0x32,
+	0x8F,
+	0x4A,
+	0x80,
+	0x18,
+	0xE5,
+	0x4C,
+	0x60,
+	0x19,
+	0x7F,
+	0x25,
+	0x12,
+	0x0C,
+	0x77,
+	0xEF,
+	0x54,
+	0x10,
+	0xF5,
+	0x4B,
+	0xB5,
+	0x47,
+	0x04,
+	0x15,
+	0x4C,
+	0x80,
+	0xEB,
+	0x85,
+	0x4B,
+	0x47,
+	0x85,
+	0x4A,
+	0x4C,
+	0x80,
+	0xE3,
+	0x22,
+	0x8F,
+	0x4A,
+	0x80,
+	0x18,
+	0xE5,
+	0x4C,
+	0x60,
+	0x19,
+	0x7F,
+	0x7F,
+	0x12,
+	0x0C,
+	0x7B,
+	0xEF,
+	0x54,
+	0x04,
+	0xF5,
+	0x4B,
+	0xB5,
+	0x3D,
+	0x04,
+	0x15,
+	0x4C,
+	0x80,
+	0xEB,
+	0x85,
+	0x4B,
+	0x3D,
+	0x85,
+	0x4A,
+	0x4C,
+	0x80,
+	0xE3,
+	0x22,
+	0x7E,
+	0x06,
+	0x7F,
+	0x00,
+	0x12,
+	0x06,
+	0x8A,
+	0x7D,
+	0x04,
+	0x7F,
+	0x0A,
+	0x30,
+	0x01,
+	0x10,
+	0x12,
+	0x06,
+	0x63,
+	0x7D,
+	0x04,
+	0x7F,
+	0x5C,
+	0x12,
+	0x06,
+	0x6F,
+	0x7D,
+	0x01,
+	0x7F,
+	0x07,
+	0x80,
+	0x00,
+	0x12,
+	0x06,
+	0x4E,
+	0x22,
+	0xAD,
+	0x07,
+	0xAC,
+	0x06,
+	0xE4,
+	0x12,
+	0x04,
+	0x9C,
+	0xE4,
+	0xFB,
+	0xFA,
+	0x79,
+	0x20,
+	0x78,
+	0x40,
+	0x12,
+	0x03,
+	0xFA,
+	0x12,
+	0x04,
+	0xD5,
+	0x8F,
+	0x11,
+	0xE5,
+	0x11,
+	0x70,
+	0xFC,
+	0x22,
+	0x78,
+	0x7F,
+	0xE4,
+	0xF6,
+	0xD8,
+	0xFD,
+	0x75,
+	0x81,
+	0xA5,
+	0x02,
+	0x02,
+	0x64 
+};
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.c b/drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.c
new file mode 100644
index 0000000..2b92556
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.c
@@ -0,0 +1,1587 @@
+/* -*- pse-c -*-
+ *-----------------------------------------------------------------------------
+ * Filename: lvds.c
+ * $Revision: 1.3 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file is contains all necessary functions for Internal
+ *  LVDS PORT DRIVER.
+ *  This is written according to the port interface defined in pd.h.
+ *-----------------------------------------------------------------------------
+ */
+
+#pragma optimize ("",off)
+
+#include <config.h>
+#include <igd_pd.h>
+#include <pd.h>
+#include <pd_print.h>
+
+#include "lvds.h"
+
+
+#ifdef T_LINUX
+	#include <linux/kernel.h>
+
+	#define PD_DEBUG printk
+	#define PD_ERROR printk
+#else
+	#define CONFIG_PLB
+//	#define CONFIG_TNC
+#endif
+
+/* One space between the #define and the backslash,else compilers complain */
+#define PTR_OFFSET_UCHAR(ptr,offset)   (*((unsigned char *)ptr + offset))
+#define PTR_OFFSET_USHORT(ptr, offset) (*(unsigned short *)((unsigned char *)ptr + offset))
+
+#define PTR_OFFSET_ULONG(ptr, offset) (*(unsigned long *)((unsigned char *)ptr + offset))
+/* END OF OPTIMIZATION MACROS */
+
+/* This constant = 10,000,000.  The value is used to
+ * get effective results from the integer math, and
+ * to not divide by 0. */
+#define PWM_FREQ_CALC_CONSTANT_1        0x00989680
+/* This constant is 1,000,000 - to multiply to get
+ * the Display Clock Frequency to the order of Mhz */
+#define PWM_FREQ_CALC_CONSTANT_2        0x000F4240
+
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(p) (sizeof(p)/sizeof((p)[0]))
+#endif
+
+static pd_version_t  internal_lvds_version = {11, 0, 0, 0}; /* driver version */
+static unsigned long internal_lvds_dab_list[] = {
+	PD_DAB_LIST_END
+}; /* dab list */
+
+static unsigned long supported_chipset[] =
+{
+#ifdef CONFIG_855
+	PCI_DEVICE_ID_VGA_855,
+#endif
+#ifdef CONFIG_915AL
+	PCI_DEVICE_ID_VGA_915AL,
+#endif
+#ifdef CONFIG_945GM
+	PCI_DEVICE_ID_VGA_945GM,
+	PCI_DEVICE_ID_VGA_945GME,
+#endif
+#ifdef CONFIG_965GM
+	PCI_DEVICE_ID_VGA_GM965,
+	PCI_DEVICE_ID_VGA_GME965,
+#endif
+#ifdef CONFIG_CTG
+	PCI_DEVICE_ID_VGA_CTG,
+#endif
+#ifdef CONFIG_PLB
+	PCI_DEVICE_ID_VGA_PLB,
+#endif
+#ifdef CONFIG_TNC
+	PCI_DEVICE_ID_VGA_TNC,
+	PCI_DEVICE_ID_VGA_TNC_A0,
+	PCI_DEVICE_ID_VGA_LNC,
+#endif
+};
+
+static pd_driver_t  internal_lvds_driver  = {
+	PD_SDK_VERSION,
+	"Internal LVDS Port Driver",
+	0,
+	&internal_lvds_version,
+	PD_DISPLAY_LVDS_INT,
+	PD_FLAG_UP_SCALING,
+	internal_lvds_dab_list,
+	100,
+	internal_lvds_validate,
+	internal_lvds_open,
+	internal_lvds_init_device,
+	internal_lvds_close,
+	internal_lvds_set_mode,
+	internal_lvds_post_set_mode,
+	internal_lvds_set_attrs,
+	internal_lvds_get_attrs,
+	internal_lvds_get_timing_list,
+	internal_lvds_set_power,
+	internal_lvds_get_power,
+	internal_lvds_save,
+	internal_lvds_restore,
+	internal_lvds_get_port_status
+};
+
+/* This is a common attribute table for all chipsets. At the end of the table
+ * there are multiple end entries to add chipset specific attributes.
+ * Chipset specific attributes:
+ *     965GM/GM45- Maintain aspect ratio
+ * Note:
+ *    1. Make sure to update the chipset_attr_index whenever adding a
+ *       chipset specific new attr.
+ */
+static pd_attr_t internal_lvds_attrs[] =
+{
+	/* Range attributes */
+
+	/*<-------ID----------->              <----TYPE-------->  <---NAME----->  <----flag---->               <---DEF_VAL---->       <--CURR_VALUE-->      min max  st */
+	PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T1,   PD_ATTR_TYPE_RANGE, "FP Power T1",  PD_ATTR_FLAG_USER_INVISIBLE, 0,                     0,                    0,  819,  1),
+	PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T2,   PD_ATTR_TYPE_RANGE, "FP Power T2",  PD_ATTR_FLAG_USER_INVISIBLE, 0,                     0,                    0,  819,  1),
+	PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T3,   PD_ATTR_TYPE_RANGE, "FP Power T3",  PD_ATTR_FLAG_USER_INVISIBLE, 0,                     0,                    0,  819,  1),
+	PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T4,   PD_ATTR_TYPE_RANGE, "FP Power T4",  PD_ATTR_FLAG_USER_INVISIBLE, 0,                     0,                    0,  819,  1),
+	PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T5,   PD_ATTR_TYPE_RANGE, "FP Power T5",  PD_ATTR_FLAG_USER_INVISIBLE, 400,                 400,                    0,  3000, 1),
+	PD_MAKE_ATTR (PD_ATTR_ID_PANEL_DEPTH, PD_ATTR_TYPE_RANGE, "Panel Depth",  PD_ATTR_FLAG_USER_INVISIBLE, LVDS_DEF_PANEL_DEPTH,  LVDS_DEF_PANEL_DEPTH, 18, 24,   6),
+
+	PD_MAKE_ATTR (PD_ATTR_ID_PWM_INTENSITY,	  PD_ATTR_TYPE_RANGE, "PWM cycle",			  PD_ATTR_FLAG_USER_INVISIBLE,		100,		0,				  0,  100,  0),
+	PD_MAKE_ATTR (PD_ATTR_ID_INVERTER_FREQ,	  PD_ATTR_TYPE_RANGE, "Inverter Frequency",	  PD_ATTR_FLAG_USER_INVISIBLE,		100,		0,				  0,  0,  0),
+	PD_MAKE_ATTR (PD_ATTR_ID_BLM_LEGACY_MODE, PD_ATTR_TYPE_BOOL,  "Backlight Legacy mode",	  PD_ATTR_FLAG_USER_INVISIBLE,		0,		0,					  0,  0,  0),
+
+	/*<-------ID------------>                 <----TYPE--------> <---NAME----->        <------flag--------------->  <---DEF_VAL---->   <--CURR_VALUE-->   <---pad--> */
+	PD_MAKE_ATTR (PD_ATTR_ID_2_CHANNEL_PANEL, PD_ATTR_TYPE_BOOL, "Dual-channel panel", PD_ATTR_FLAG_USER_INVISIBLE, 0,                 0,                 0, 0, 0),
+	PD_MAKE_ATTR (PD_ATTR_ID_LVDS_PANEL_TYPE, PD_ATTR_TYPE_BOOL, "Panel Type",         PD_ATTR_FLAG_USER_INVISIBLE, 0,                 0,                 0, 0, 0),
+	PD_MAKE_ATTR (PD_ATTR_ID_PANEL_FIT,       PD_ATTR_TYPE_BOOL, "Panel Upscale",      PD_ATTR_FLAG_USER_INVISIBLE, LVDS_DEF_PANEL_FIT,LVDS_DEF_PANEL_FIT,0, 0, 0),
+	PD_MAKE_ATTR (PD_ATTR_ID_DITHER,          PD_ATTR_TYPE_BOOL, "Dither",             PD_ATTR_FLAG_USER_INVISIBLE, LVDS_DEF_DITHER,   LVDS_DEF_DITHER,   0, 0, 0),
+	PD_MAKE_ATTR (LVDS_ATTR_ID_TC_LVDS_CLK,   PD_ATTR_TYPE_BOOL, "TC LVDS CLK 110MHz", PD_ATTR_FLAG_USER_INVISIBLE, 0,                 0,                 0, 0, 0),
+
+	/* Start of chipset specific attributes */
+	/* Maintain aspect ratio */
+	PD_MAKE_ATTR (PD_ATTR_LIST_END,       0,                   "",            0,                           0,                0,               0,     0, 0),
+	/* Text tuning */
+	PD_MAKE_ATTR (PD_ATTR_LIST_END,       0,                   "",            0,                           0,                0,               0,     0, 0),
+
+	/* Attribute list end */
+	PD_MAKE_ATTR (PD_ATTR_LIST_END,       0,                   "",            0,                           0,                0,               0,     0, 0)
+};
+
+/* Rightnow it is -3 to reach starting of chipset specific attributes */
+static unsigned short chipset_attr_index = (unsigned short)
+	sizeof(internal_lvds_attrs)/sizeof(pd_attr_t) - 3;
+
+#if 0
+static pd_attr_t internal_lvds_965gm_attrs[] = {
+	PD_MAKE_ATTR (PD_ATTR_ID_MAINTAIN_ASPECT_RATIO,PD_ATTR_TYPE_BOOL,      "Maintain Aspect Ratio",0,             0,               0,               0,     0, 0),
+	PD_MAKE_ATTR (PD_ATTR_ID_TEXT_TUNING,          PD_ATTR_TYPE_RANGE,     "Text Enhancement",     0,             0,               0,               0,     2, 1),
+};
+#endif
+
+static void internal_lvds_write_reg(internal_lvds_context_t *pd_context, unsigned long reg,
+		unsigned long value, unsigned long change_bits, unsigned long reg_type);
+
+static unsigned long internal_lvds_read_reg(internal_lvds_context_t *pd_context,
+		unsigned long reg, unsigned long reg_type);
+static void internal_lvds_panel_fit(internal_lvds_context_t *pd_context);
+
+static void internal_lvds_get_dclk(internal_lvds_context_t *pd_context, pd_dvo_info_t *internal_lvds_info);
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: PD_MODULE_INIT(internal_lvds_init)
+ *
+ * Description:
+ *    This is the entry function into LVDS port driver when
+ *    it first loads. This will call pd_register() to register
+ *    with Display driver.  Only the driver object is initialized in this
+ *    function, similar to DrverEntry() in a WDM driver.
+ *
+ * Parameters:
+ *    [OUT] *handle:  Not used.  Place holder for supporting dynamic pd
+ *
+ * Return:
+ *    PD_SUCCESS(0)  success
+ *    PD_ERR_XXXXXX  otherwise
+ *
+ *----------------------------------------------------------------------------
+ */
+#ifdef T_LINUX //thua- 9/16/11
+
+int PD_MODULE_INIT(internal_lvds_init, (void *handle))
+{
+	/* register the LVDS driver */
+	return pd_register(handle, &internal_lvds_driver);
+}
+
+#endif
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: PD_MODULE_EXIT(internal_lvds_exit, (void))
+ *
+ * Description:
+ *    This function cleans up resources used by the LVDS driver
+ *
+ * Parameters:
+ *    None
+ *
+ * Return:
+ *    PD_SUCCESS(0):  always returns this
+ *
+ *----------------------------------------------------------------------------
+ */
+#ifdef T_LINUX //thua- 9/16/11
+int PD_MODULE_EXIT(internal_lvds_exit, (void))
+{
+	return PD_SUCCESS;
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_validate
+ *
+ * Description:
+ *    Place holder for a future function
+ *
+ * Parameters:
+ *    TBD
+ *
+ * Return:
+ *    TBD
+ *
+ *----------------------------------------------------------------------------
+ */
+
+unsigned long internal_lvds_validate (unsigned long cookie)
+{                                                          /* internal_lvds_validate */
+	/* Validate magic cookie */
+	/* TODO: Implement the magic cookie algorithm */
+	return cookie;
+}                                                          /* internal_lvds_validate */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_open
+ *
+ * Description:
+ *    This function creates an LVDS context and intialize it with LVDS
+ *    attributes.
+ *
+ *    Internal LVDS port is available only on MGM platform, this port driver
+ *    reads the GMCH device ID with pd_read_regs(PD_REG_PCI) to verify that
+ *    it is supported on the current platform.
+ *
+ * Parameters:
+ *    [IN] callback:    callback context
+ *    [INOUT] context:  Device context.  This function will set the attributes
+ *                      for this context, provided it is already allocated,
+ *                      i.e. not NULL.
+ *
+ * Return:
+ *    PD_ERR_NULL_PTR:  if either of the parameters is NULL
+ *    PD_ERR_NODEV:     if an LVDS device is already up and running
+ *    PD_ERR_NOMEM:     if a memory allocation failed
+ *    PD_SUCCESS:       if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* lvds context structure being declared and initialized */
+
+static internal_lvds_context_t internal_lvds_context = {  /* lvds context structure */
+	0,                   /* fp_width     */
+	0,                   /* fp_height    */
+	0,                   /* dual_channel: Default single channel */
+	0,                   /* panel_type : 0-SPWG 1-OpenLDI*/
+	LVDS_DEF_PANEL_FIT,  /* panel_fit    */
+	LVDS_DEF_PANEL_DEPTH,/* panel_depth  */
+	0xFFFF,              /* dither       */
+	0,                   /* Main aspect ratio, default no */
+	0,                   /* panel filter: Default fuzzy filtering */
+	100,                 /* PWM Intensity */
+	0xFFFF,              /* Inverter Frequency*/
+	0,                   /* BLM Legacy Mode */
+
+	PD_POWER_MODE_D0,    /* power_state   */
+	0,                   /* chipset       */
+	0,                   /* init_done     */
+	0,                   /* num_attrs */
+	0,                   /* PIPE flags    */
+	0,                   /* Graphics Frequency */
+	0,                   /* is gn4 based LVDS controller? */
+	0,                   /* is pwm_done? */
+	0,                   /* is tc_110MHz_clk? i.e., TC max LVDS to 110MHz*/
+
+	NULL,                /* ptr to callback       */
+	NULL,                /* ptr to timing table   */
+	internal_lvds_attrs,          /* ptr to attribute list */
+	NULL,                /* ptr to native timing  */
+	NULL,                /* current mode */
+};
+
+int internal_lvds_open(pd_callback_t *callback, void **context)
+{                                                              /* internal_lvds_open */
+	internal_lvds_context_t *pd_context = (internal_lvds_context_t*) &(internal_lvds_context); /* static Global */
+	pd_reg_t reg_list[2];
+	int ret, i, valid_chipset = 0;
+	unsigned short chipset;
+
+	PD_TRACE_ENTER;
+
+
+
+	/* make sure parameters are valid */
+	if (!callback || !context) {
+		PD_ERROR("invalid parameter");
+		return (PD_ERR_NULL_PTR);
+	}
+	/* GMCH cannot support more than one device */
+	if (internal_lvds_driver.num_devices > 0) {
+		return (PD_ERR_NODEV);
+	}
+	/* Verify that this is an GMCH with Internal LVDS available */
+	reg_list[0].reg = 2;
+	reg_list[1].reg = PD_REG_LIST_END;
+	ret = callback->read_regs(callback->callback_context, reg_list, PD_REG_PCI);
+	if(ret != PD_SUCCESS) {
+		return ret;
+	}
+	chipset = (unsigned short)(reg_list[0].value & 0xffff);
+	for (i = 0; i < ARRAY_SIZE(supported_chipset); i++) {
+		if (chipset == supported_chipset[i]){
+			valid_chipset = 1;
+			break;
+		}
+	}
+	if(!valid_chipset){
+		return PD_ERR_NODEV;
+	}
+
+	/* Special handling for gn4 and beyond chipsets */
+	if (chipset == PCI_DEVICE_ID_VGA_GM965 ||
+		chipset == PCI_DEVICE_ID_VGA_GME965 ||
+		chipset == PCI_DEVICE_ID_VGA_CTG ||
+		chipset == PCI_DEVICE_ID_VGA_TNC ||
+		chipset == PCI_DEVICE_ID_VGA_TNC_A0 ||
+		chipset == PCI_DEVICE_ID_VGA_LNC) {
+		internal_lvds_context.gn4_plus = 1;
+	}
+
+	/* Initialize number of attributes */
+	/* +1 is to include the end attribute */
+	internal_lvds_context.num_attrs = (unsigned char)chipset_attr_index;
+//	internal_lvds_context.num_attrs = (unsigned char)chipset_attr_index + 1;
+
+#if 0
+	/* Add chipset specific attrbutes.
+	 * This can be expanded into a switch statement in future if required. */
+	if (internal_lvds_context.gn4_plus) {
+		internal_lvds_context.num_attrs += sizeof(internal_lvds_965gm_attrs)/sizeof(pd_attr_t);
+		for (i=0; i < sizeof(internal_lvds_965gm_attrs)/sizeof(pd_attr_t); i++) {
+			internal_lvds_attrs[chipset_attr_index+i] = internal_lvds_965gm_attrs[i];
+		}
+	}
+#endif
+
+	/* Make this a compile time so that size of vBIOS doesn't become > 64KB */
+#if defined(CONFIG_PLB) || defined(CONFIG_TNC)
+	/* pwm backlight control needs graphics frequency. we currently implement
+	 * pwm backlight control for pouslbo only to limit the vbios lvds size. Each
+	 * chipset have a different method of getting this value and chipset has a
+	 * different multiplier. */
+	if (chipset == PCI_DEVICE_ID_VGA_PLB || 
+	    chipset == PCI_DEVICE_ID_VGA_TNC ||
+	    chipset == PCI_DEVICE_ID_VGA_TNC_A0 ||
+	    chipset == PCI_DEVICE_ID_VGA_LNC) {
+
+		/* For plb/tnc, graphics frequency is obtained by sending an opcode to
+		 * port 5 in the SCH Message Network. We call the read_regs with
+		 * PD_REG_BRIDGE_OPCODE specifically for this purpose only.
+		 *
+		 * The input for this read_reg is the opcode that register data that
+		 * we send into the Message control register*/
+		reg_list[1].reg = PD_REG_LIST_END;
+		ret = callback->read_regs(callback->callback_context,
+			reg_list, PD_REG_BRIDGE_OPCODE);
+		if(ret != PD_SUCCESS) {
+			return ret;
+		}
+
+		/*set the graphics frequency*/
+		pd_context->gfx_freq = (unsigned short) reg_list[0].value;
+	}
+#endif
+
+	pd_context->callback = callback;           /* Save callback context */
+	pd_context->chipset = chipset;            /* save the chipset ID   */
+	*context = (void *) pd_context;
+
+	PD_TRACE_EXIT;
+	return PD_SUCCESS;
+}                                                              /* internal_lvds_open */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_init_device
+ *
+ * Description:
+ *    Initializes the LVDS device, using the device context from the parameter
+ *
+ * Parameters:
+ *    [INOUT] context:  device context
+ *
+ * Return:
+ *    PD_ERR_NULL_PTR:  if parameter is invalid
+ *    PD_SUCCESS:       if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int internal_lvds_init_device (void *context)
+{                                                       /* internal_lvds_init_device */
+	if (!context) {
+		return (PD_ERR_NULL_PTR);
+	}
+
+	/* Don't need to do much to initialize this device */
+	((internal_lvds_context_t *)context)->init_done = 1;
+	internal_lvds_driver.num_devices++;
+
+	return (PD_SUCCESS);
+}                                                       /* internal_lvds_init_device */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_close
+ *
+ * Description:
+ *    Releases resources allocated during internal_lvds_open().  This function
+ *    essentially frees a device object.
+ *
+ * Parameters:
+ *    [INOUT] device_context:  device to be freed
+ *
+ * Return:
+ *    PD_SUCCESS: always returns this
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int internal_lvds_close(void *device_context)
+{
+#ifndef CONFIG_MICRO
+
+	internal_lvds_context_t *pd_context = (internal_lvds_context_t *)device_context;
+
+	/* internal_lvds_close */
+	
+	PD_TRACE_ENTER;
+
+	/* Deallocate memory occupied by this device */
+	if (device_context) {
+		if ( NULL != pd_context->timing_table) {
+			pd_free(pd_context->timing_table);
+		}
+
+		/* Free attribute list, if necessary */
+		/* FIXME -- The following test will never call pd_free(), because the
+		 * expression "!internal_lvds_driver.num_devices" will yield 0 or 1, and that
+		 * will never be greater than 1.  This is a potentially small memory
+		 * leak, unless some other code frees it.
+		 */
+		if (!internal_lvds_driver.num_devices > 1) {
+			pd_free(pd_context->attr_list);
+		}
+		/* This allocated statically no need to free it */
+		/* pd_free(device_context); */
+		internal_lvds_driver.num_devices--;
+		pd_context->init_done = 0;
+	}
+
+	PD_TRACE_EXIT;
+#endif
+	return (PD_SUCCESS);
+}                                                             /* internal_lvds_close */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_set_mode
+ *
+ * Description:
+ *    Sets LVDS to a new mode, specified by "mode".
+ *
+ * Parameters:
+ *    [INOUT] context:  device context
+ *    [IN]    mode:     information about the mode to switch to
+ *    [IN]    flags:    can contain the following value
+ *                PD_SET_MODE_FLAG_TEST:  only testing to see if mode is supported
+ *
+ * Return:
+ *    PD_ERR_NULL_PTR:     if invalid parameter detected
+ *    PD_ERR_MODE_NOTSUPP: if mode specified is not supported
+ *    PD_SUCCESS:          if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+int internal_lvds_set_mode(void *context, pd_timing_t *mode, unsigned long flags)
+{
+	internal_lvds_context_t *pd_context  = NULL;
+
+	PD_DEBUG("internal_lvds_set_mode)\n");
+	PD_TRACE_ENTER;
+
+	pd_context = (internal_lvds_context_t *)context;
+
+	/* Make sure these parameters are valid */
+	if (!pd_context || !mode) {
+		return (PD_ERR_NULL_PTR);
+	}
+	PD_DEBUG("internal_lvds_set_mode: %ux%u", mode->width, mode->height);
+
+	/* Make sure specified mode is supported */
+	if ((pd_context->fp_width && (mode->width > pd_context->fp_width)) ||
+		(pd_context->fp_height && (mode->height > pd_context->fp_height))) {
+		PD_ERROR("internal_lvds_set_mode: ERROR #1\n");
+		return PD_ERR_MODE_NOTSUPP;
+	}
+
+	/* Do nothing if we are only want to know if a mode is supported */
+	if (flags & PD_SET_MODE_FLAG_TEST) {
+		PD_ERROR("internal_lvds_set_mode: SUPPORTED #2\n");
+		return PD_SUCCESS;
+	}
+
+	pd_context->current_mode = mode;
+	pd_context->pipe = flags;
+	/* Enable panel fitting and return */
+	internal_lvds_panel_fit(pd_context);
+  
+	PD_ERROR("internal_lvds_set_mode: EXIT #3\n");
+	PD_TRACE_EXIT;
+
+	return PD_SUCCESS;
+}
+
+int internal_lvds_post_set_mode(void *context, pd_timing_t *mode, unsigned long flags)
+{                                                          /* internal_lvds_set_mode */
+	internal_lvds_context_t *pd_context  = NULL;
+	unsigned long  port_control = 0;
+	unsigned long  preserve     = 0;
+	int            ret          = 0;
+
+	PD_TRACE_ENTER;
+	pd_context = (internal_lvds_context_t *)context;
+
+	PD_DEBUG("internal_lvds_post_set_mode)\n");
+	/* Make sure these parameters are valide */
+	if (!pd_context || !mode) {
+		PD_DEBUG("internal_lvds_post_set_mode: EXIT #1\n");
+		return (PD_ERR_NULL_PTR);
+	}
+
+	/* Before enabling the LVDS port, make sure that display PLL for this pipe
+	 * is enabled and the port is power sequenced on using the panel power
+	 * sequencing logic. */
+
+	preserve = 0x3E007803;
+	port_control = preserve & internal_lvds_read_reg(pd_context, 0x61180, PD_REG_MIO);
+	port_control |= BIT(31);          /* enable LVDS port */
+	if (flags & PD_SET_MODE_PIPE_B) {
+		port_control |= BIT(30);
+	}
+	port_control |= (BIT(9)|BIT(8));  /* power up */
+	port_control &= ~(BIT(21)|BIT(20)); /* Default sync polarites active high */
+
+	/* For gn4+, dither moved to port_control from panel_fit reg */
+	if (pd_context->gn4_plus) {
+		if (pd_context->panel_depth == 18) {
+			port_control |= BIT(25);
+		}
+
+		if (pd_context->dither != 0xFFFF) {
+			if (pd_context->dither) {
+				port_control |= BIT(25);
+			} else {
+				port_control &= ~BIT(25);
+			}
+		}
+	}
+
+	if((!pd_context->panel_fit) &&
+	   ( mode->width < pd_context->fp_width ||
+	     mode->height < pd_context->fp_height ) ){
+		port_control |= BIT(15); /* enable border in active for centering */
+	}
+
+	/*
+	 * Bit 24 for OpenLDI should be set to a 0 (1x18.0, 2x18.0, 1x24.0, 2x24.0).
+	 * From (B-Spec, Ref# 22316, section 1.15.3.8.3)
+	 *
+	 * Bit 24 for SPWG should be set to a 1 (1x24.1 or 2x24.1).
+	 *
+	 * This was verified by comparing the timing diagram for 1x24.0 in
+	 * OpenLDI spec (5.4.2.2 24-bit Single Pixel Mode, Unbalanced) with the
+	 * same diagram in the Display BSpec for Napa or Gen4.
+	 * A0 – A3 signals match the 1x24.0.
+	 *
+	 * From the OpenLDI spec (bit mappings are different):
+	 *
+	 * Table 5-2, Bit Number Mappings
+	 * 18 bpp bit# 24 bpp bit# OpenLDI bit#
+	 * 5           7           5
+	 * 4           6           4
+	 * 3           5           3
+	 * 2           4           2
+	 * 1           3           1
+	 * 0           2           0
+	 *             1           7
+	 *             0           6
+	 */
+
+	/* Attribute panel_type description:
+	 *  Attr ID    Attr Value        IntLVDS dataformat
+	 *  =======    ===============   ==================
+	 *    49       0  (SPWG)           1 (value of Bit 24)
+	 *    49       1  (OpenLDI)        0 (value of Bit 24)
+	 */
+	if (pd_context->panel_type == 0) {
+		port_control |= BIT(24); /* Dataformat 0 = SPWG, 1 = OpenLDI */
+	}
+
+	/* If the dual-channel is required, then power up second channel
+	 * ClkB and B0, B1, B2, (B3) */
+	if (pd_context->dual_channel) {
+		port_control |= (BIT(5)|BIT(4));  /* ClkB */
+		port_control |= (BIT(3)|BIT(2));  /* B0, B1, B2, (B3) */
+	}
+
+	/* Check for 18 or 24 bit panel */
+	if (pd_context->panel_depth == 24) {
+		/* If the panel is 24-bit (8-bpp), enable A3, (B3) pair. */
+		port_control |= (BIT(7)|BIT(6));
+	}
+
+	/* Set the sync polarities correctly if there is a native dtd */
+	if (pd_context->native_dtd) {
+		/* Set bit 20 for hsync active low */
+		if ((pd_context->native_dtd->mode_info_flags & PD_HSYNC_HIGH) == 0) {
+			port_control |= BIT(20);
+		}
+		/* Set bit 21 for vsync active low */
+		if ((pd_context->native_dtd->mode_info_flags & PD_VSYNC_HIGH) == 0) {
+			port_control |= BIT(21);
+		}
+	}
+
+    internal_lvds_write_reg(pd_context, 0x61204, 0xABCD0000, 0xFFFFFFFF, PD_REG_MIO);
+
+	internal_lvds_write_reg(pd_context, 0x61180, port_control, 0xFFFFFFFF, PD_REG_MIO);
+	ret = internal_lvds_set_power(pd_context, PD_POWER_MODE_D0);
+	if (ret) {
+		PD_ERROR("PD set_power (D0) returned: 0x%x", ret);
+		return ret;
+	}
+
+    internal_lvds_write_reg(pd_context, 0x61204, BIT(1), BIT(1), PD_REG_MIO);
+
+	PD_DEBUG("internal_lvds_post_set_mode: EXIT SUCCESS\n");
+
+	PD_TRACE_EXIT;
+	/* Set the mode as per given timings */
+	return PD_SUCCESS;
+}                                                          /* internal_lvds_set_mode */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_set_attrs
+ *
+ * Description:
+ *    Incorporate attributes in "list" into the device context.  This function
+ *    will override the initial attributes set by init_attrs.
+ *
+ * Parameters:
+ *    [INOUT] context:  device context
+ *    [IN] num:         not used, but must not be 0.
+ *    [IN] list:        list of attributes to incorporate into device context
+ *
+ * Return:
+ *    PD_ERR_NULL_PTR:          if one of the parameters is invalid
+ *    PD_ERR_ATTR_CANT_CHANGE:  attributes cannot be modified
+ *    PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+/* Tables required by Optimization Code. internal_lvds_set_attrs() */
+typedef struct _opt_table_data {
+	unsigned long id;
+	unsigned short block;
+	unsigned short offset;
+} internal_lvds_opt_table_data_t;
+static internal_lvds_opt_table_data_t table_opt_data1[] = {
+
+	/*<--- id ---------->  <---block---> <------ offset -------------------> */
+	{PD_ATTR_ID_PANEL_DEPTH,     1, PD_OFFSETOF(internal_lvds_context_t, panel_depth) },
+
+	{PD_ATTR_ID_2_CHANNEL_PANEL, 1, PD_OFFSETOF(internal_lvds_context_t, dual_channel)},
+	{PD_ATTR_ID_LVDS_PANEL_TYPE, 1, PD_OFFSETOF(internal_lvds_context_t, panel_type) },
+	{PD_ATTR_ID_PANEL_FIT,       1, PD_OFFSETOF(internal_lvds_context_t, panel_fit)   },
+	{PD_ATTR_ID_DITHER,          1, PD_OFFSETOF(internal_lvds_context_t, dither)      },
+	{PD_ATTR_ID_MAINTAIN_ASPECT_RATIO,1,PD_OFFSETOF(internal_lvds_context_t,aspect_ratio)},
+	{PD_ATTR_ID_TEXT_TUNING,     1, PD_OFFSETOF(internal_lvds_context_t, text_tune)},
+	{PD_ATTR_ID_PWM_INTENSITY,   1, PD_OFFSETOF(internal_lvds_context_t, pwm_intensity)},
+	{PD_ATTR_ID_INVERTER_FREQ,   1, PD_OFFSETOF(internal_lvds_context_t, inverter_freq)},
+	{PD_ATTR_ID_BLM_LEGACY_MODE, 1, PD_OFFSETOF(internal_lvds_context_t, blm_legacy_mode)},
+	{LVDS_ATTR_ID_TC_LVDS_CLK,   1, PD_OFFSETOF(internal_lvds_context_t, tc_110MHz_clk)},
+
+	/*<--- id ---------->  <---block---> <------ offset -------------------> */
+	{PD_ATTR_ID_FP_PWR_T1,       2,     0 }, /* 6 */
+	{PD_ATTR_ID_FP_PWR_T2,       2,     0 }, /* 7 */
+	{PD_ATTR_ID_FP_PWR_T3,       2,     0 }, /* 8 */
+	{PD_ATTR_ID_FP_PWR_T4,       2,     0 }, /* 9 */
+	{PD_ATTR_ID_FP_PWR_T5,       2,     0 }  /* 10 */
+};
+/* End of Tables required by Optimization Code. internal_lvds_set_attrs() */
+
+int internal_lvds_set_attrs (void *context, unsigned long num, pd_attr_t *list)
+{
+	internal_lvds_context_t *pd_context = (internal_lvds_context_t *) context;
+	pd_attr_t      *attr       = NULL;
+	unsigned short i           = 0;
+	unsigned short j           = 0;
+	int            ret         = PD_SUCCESS;
+	/* no of case IDs in the global table */
+	int num_case_ids = sizeof(table_opt_data1)/sizeof(internal_lvds_opt_table_data_t);
+
+	/* basic parameter check */
+	if (!context || !num || !list) {
+		return PD_ERR_NULL_PTR;
+	}
+
+	PD_DEBUG("internal_lvds_set_attrs()\n");
+	for (i = 0; i < num; i++, list++) {
+		/* do nothing if the attribute has not been changed */
+		if (!(list->flags & PD_ATTR_FLAG_VALUE_CHANGED)) {
+			continue;
+		}
+
+		//thua- need to reset flag to 'not changed' - 9/19/11
+//		list->flags &= ~PD_ATTR_FLAG_VALUE_CHANGED;
+
+		/* attributes can't be changed after init has been completed */
+		if (list->flags & PD_ATTR_FLAG_USER_INVISIBLE &&
+			pd_context->init_done) {
+			return PD_ERR_ATTR_CANT_CHANGE;
+		}
+
+		/* Set the internal attributes' list.  Note that although get_attr() can
+		 * return NULL theortically, it will not do so here because all the
+		 * attribute IDs in this switch statement comes from internal_lvds_attrs[],
+		 * a list that is automatically initialized into pd_context.  This is
+		 * why we are not checking for NULL after calling get_attr().
+		 */
+#if 0	/* ORIGINAL SWITCH STATEMENT */
+		switch (list->id) {
+			case PD_ATTR_ID_FP_PWR_T1:
+			case PD_ATTR_ID_FP_PWR_T2:
+			case PD_ATTR_ID_FP_PWR_T3:
+			case PD_ATTR_ID_FP_PWR_T4:
+			case PD_ATTR_ID_FP_PWR_T5:
+				/* current_value should not exceed the predefined max value */
+				attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+					list->id, 0);
+				attr->current_value = LVDS_MIN(
+						((pd_range_attr_t *)list)->current_value,
+						attr->_pad1);
+				break;
+
+			case PD_ATTR_ID_PANEL_DEPTH:
+				attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+					list->id, 0);
+				attr->current_value = list->current_value;
+				pd_context->panel_depth = (unsigned char) attr->current_value;
+				break;
+
+			case PD_ATTR_ID_2_CHANNEL_PANEL:
+				attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+					list->id, 0);
+				attr->current_value = ((pd_bool_attr_t *)list)->current_value;
+				pd_context->dual_channel = (attr->current_value?1:0);
+				break;
+
+			case PD_ATTR_ID_LVDS_PANEL_TYPE:
+				attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+					list->id, 0);
+				attr->current_value = ((pd_bool_attr_t *)list)->current_value;
+				pd_context->panel_type = (attr->current_value?1:0);
+				break;
+
+			case PD_ATTR_ID_PANEL_FIT:
+				attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+					list->id, 0);
+				attr->current_value = ((pd_bool_attr_t *)list)->current_value;
+				pd_context->panel_fit = (attr->current_value?1:0);
+				break;
+
+			default:
+				/* do nothing if we have an unknown ID */
+				break;
+		}
+#endif
+		/* OPTIMIZATION CODE BEGINS FOR THE ABOVE SWITCH
+		 *----------------------------------------------
+		 * Step 1: First identify the code common to all case blocks.
+		 *         This we call it "common code block" Since this is to be
+		 *         executed by all the case blocks.
+		 *
+		 * Step 2: Group the cases into blocks based on how we can combine them
+		 *
+		 *         Eg: case 0: ptr->x = 1; break; // similar code
+		 *        case 1: ptr->y = 1; break; // similar code
+		 *  ------Combined block ----
+		 *        case 0:
+		 *        case 1: PTR_OFFSET_TYPE(ptr, table[i].offset) = 1; break;
+		 *        This is an important step because we save code space by
+		 *        mapping many cases to smaller number of blocks. In the above
+		 *        we use index to get the right offset of the ptr.
+		 *
+		 * Step 3: Assign block IDs to each block. Put the case ID, block ID
+		 *         and other information such as offsets of ptr in a global
+		 *         table.
+		 *
+		 * Step 4: During run-time , search through the global table, find the
+		 *         matching case ID, and execute the common code. Next get the
+		 *         block ID and execute the block specific code. For the index,
+		 *         retrieve it from the table for the corresponding case ID.
+		 *
+		 * Step 5: If no matching case ID is found, error it out.
+		 *
+		 * Let's look at the optimization code for the above switch.
+		 * The code below searches for the list->id in a global table where
+		 * we store all the case values along with block numbers and other
+		 * information. After we find a valid id in the table , we execute the
+		 * common code for all cases first and then we retrieve the block id.
+		 * The block id is necesary to determine which block does the id belong
+		 * to. This is used to execute block specific code. Similar to switch
+		 * cases ONLY here we try to minimize the no of blocks.
+		 *
+		 * In this example , we store the offsets of field names of a ptr in the
+		 * global table.This is necessary to combine cases with "similar" but
+		 * not "same" codes.
+		 *
+		 * Eg: case 0: ptr->x = 1; break; // similar code
+		 *     case 1: ptr->y = 1; break; // similar code
+		 *  -- Combined block ----
+		 *    case 0:
+		 *    case 1: PTR_OFFSET_TYPE(ptr, table[i].offset) = 1; break;
+		 *
+		 * By reducing the number of blocks we save on Code space. After we
+		 * finish our work , we exit the for loop and check for invalid ID
+		 * passed by the upper layer. This is akin to default in the
+		 * switch block
+		 *
+		 * CAUTION: If there is any change in the switch above, this code
+		 * along with the tables have to be re-written and changed according
+		 * to the new behaviour of the switch. Examples include adding a new
+		 * case in the switch. The reason for all this mumbo-jumbo is to
+		 * reduce code size in VBIOS, where we are running out of code space.
+		 */
+		for(j = 0; j < num_case_ids; j++) {
+			/* Search for the attribute ID in the global table */
+			if(list->id == table_opt_data1[j].id) {
+				/* Run the common code for all the blocks */
+				attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+					list->id, 0);
+				/* Once we get a valid ID, need to find out which block it
+				 *  belongs so we can execute block specific code.
+				 */
+				if(table_opt_data1[j].block == 1) { /* block 1 */
+					/* Got the block. Need the offset to the struct for that ID
+					* so we can store value at corresponding offset to get the
+					* desired behaviour for that ID.This is the code that makes
+					* the whole optimization work because we are combining the
+					* case IDs into a single block which saves code.
+					*/
+					attr->current_value = list->current_value;
+					PTR_OFFSET_USHORT(pd_context, table_opt_data1[j].offset) =
+					(unsigned short) attr->current_value;
+
+				} else { /* block 2. We only have two blocks. */
+					attr->current_value = LVDS_MIN(
+						list->current_value, ((pd_range_attr_t *)attr)->max);
+				}
+				break; /* We found a valid ID, so break inner for loop */
+			}
+		}
+	}
+	/* panel_type 0 (SPWG) isn't available for 18-bit depth */
+	PD_DEBUG("in LVDS_set_attributes()\n");
+	if (pd_context->panel_depth == 18) {
+		pd_context->panel_type = 1;
+	}
+	PD_DEBUG("IntLVDS: dual_channel=%u", pd_context->dual_channel);
+	PD_DEBUG("IntLVDS: panel_type=%u panel_fit=%u panel_dep=%u dither=%u",
+		pd_context->panel_type, pd_context->panel_fit,
+		pd_context->panel_depth, pd_context->dither);
+	PD_DEBUG("IntLVDS: keep_aspect_ratio=%u text_tune=%lu",
+		pd_context->aspect_ratio, pd_context->text_tune);
+	PD_DEBUG("IntLVDS: PWM Intensity=%u Inverter Freq=%u, BLM legacy mode =%u",
+		pd_context->pwm_intensity, pd_context->inverter_freq,
+		pd_context->blm_legacy_mode);
+	PD_DEBUG("IntLVDS: tc_110MHz_clk = %u", pd_context->tc_110MHz_clk);
+
+	if (pd_context->init_done) {
+		/* When emgd_driver_pre_init() pokes new attrs into this port driver,
+		 * pd_context->current_mode must be set before calling
+		 * internal_lvds_panel_fit(), so set it to the first entry in the timing table:
+		 */
+		if (pd_context->current_mode == NULL) {
+			pd_context->current_mode = pd_context->timing_table;
+		}
+		internal_lvds_panel_fit(pd_context); 
+	}
+
+	return ret;
+} /* internal_lvds_set_attrs */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_get_attrs
+ *
+ * Description:
+ *    Extracts the attribute list and the number of elements in the list
+ *    from the device context.
+ *
+ * Parameters:
+ *    [IN] context: device context to extract information from
+ *    [OUT] num:    number of elements in list
+ *    [OUT] list:   list of attributes from the device context
+ *
+ * Return:
+ *    PD_ERR_NULL_PTR: if one of the parameters is invalid
+ *    PD_SUCCESS:      if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+int internal_lvds_get_attrs (void *context, unsigned long *num, pd_attr_t **list)
+{                                                         /* internal_lvds_get_attrs */
+	/* basic parameter check */
+	if (!context || !num || !list) {
+		return PD_ERR_NULL_PTR;
+	}
+
+	PD_DEBUG("internal_lvds_get_attrs()\n");
+	/* Nothing fancy, just extracting the elements from the list */
+	*list = ((internal_lvds_context_t *)context)->attr_list;
+	*num  = ((internal_lvds_context_t *)context)->num_attrs;
+
+	return PD_SUCCESS;
+}                                                         /* internal_lvds_get_attrs */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_get_timing_list
+ *
+ * Description:
+ *
+ *
+ * Parameters:
+ *    [IN] context: device context to extract information from
+ *    [OUT] in_list:
+ *    [OUT] list:
+ *
+ * Return:
+ *    PD_ERR_NULL_PTR: if one of the parameters is invalid
+ *    PD_ERR_NOMEM:    if internal memory allocate failed
+ *    PD_SUCCESS:      if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+int internal_lvds_get_timing_list (void *context, pd_timing_t *in_list,
+	pd_timing_t **list)
+{                                                   /* internal_lvds_get_timing_list */
+	internal_lvds_context_t *pd_context = (internal_lvds_context_t *)context;
+	pd_dvo_info_t internal_lvds_info = {0, 0, 1, 0, 0, 0, 0, 0};
+	pd_display_info_t internal_lvds_display_info = {0, 0, 0, 0, NULL};
+	int ret;
+
+	PD_DEBUG("internal_lvds_get_timing_list()\n");
+	
+	PD_DEBUG ("NUHAIRI : context = %lu,  pd_context = %lu, &internal_lvds_info = %lu\n",context,  pd_context, &internal_lvds_info);
+	
+	internal_lvds_get_dclk( pd_context, &internal_lvds_info );
+
+	PD_DEBUG("chipset = 0x%x", pd_context->chipset);
+	internal_lvds_display_info.panel_fit = (unsigned char) pd_context->panel_fit;
+	ret = pd_filter_timings(pd_context->callback->callback_context,
+		in_list, &pd_context->timing_table, &internal_lvds_info, &internal_lvds_display_info);
+
+	/* Helper function will return the below values */
+	pd_context->native_dtd = internal_lvds_display_info.native_dtd;
+	pd_context->fp_width = internal_lvds_display_info.width;
+	pd_context->fp_height = internal_lvds_display_info.height;
+
+	*list = pd_context->timing_table;
+	return ret;
+}                                                   /* internal_lvds_get_timing_list */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_set_power
+ *
+ * Description:
+ *  Sets LVDS to the specified power state
+ *
+ *  Conversion between IEGD timer values to LVDS port timer values
+ *
+ *  SEPG(?) IEGD    LVDS Port    Program bits     min     max
+ *  ----    ------- ------------ ---------------- ------ ---------
+ *  T1+T2   T1 ms   T1+T2 100us  0x61208 [28:16]  0 ms   819.2 ms
+ *  T5      T2 ms   T5    100us  0x61208 [12:00]  0 ms   819.2 ms
+ *  T6      T3 ms   Tx    100us  0x6120C [12:00]  0 ms   819.2 ms
+ *  T3      T4 ms   T3    100us  0x6120C [28:16]  0 ms   819.2 ms
+ *  T4      T5 ms   T4    100ms  0x61210 [04:00]  0 ms   3200  ms
+ *
+ *  Reg     = Value
+ *  ------    -------
+ *  0x61208 = [T1 T2]
+ *  0x6120C = [T4 T3]
+ *  0x61210 = [   T5]
+ *
+ * Parameters:
+ *    [IN] context: device context to extract information from
+ *    [OUT] in_list:
+ *    [OUT] list:
+ *
+ * Return:
+ *    PD_ERR_NULL_PTR:      if context is NULL
+ *    PD_ERR_INVALID_POWER: if "state" is invalid
+ *    PD_SUCCESS:           if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+/* Tables required by the optimization codes in internal_lvds_set_power() */
+typedef struct {
+	unsigned char id1;
+	unsigned char id2;
+	unsigned char bit;
+	unsigned long reg;
+} opt_set_power_t;
+
+static opt_set_power_t table_set_power[] = {
+	/* id1                  id2                   bit    reg */
+	{ PD_ATTR_ID_FP_PWR_T1, PD_ATTR_ID_FP_PWR_T2, 1,     0x61208 },  /* D0 */
+	{ PD_ATTR_ID_FP_PWR_T4, PD_ATTR_ID_FP_PWR_T3, 0,     0x6120C },  /* Dx */
+};
+
+int internal_lvds_set_power(void *context, unsigned long state)
+{                                                         /* internal_lvds_set_power */
+	unsigned long  i           = 0;
+	internal_lvds_context_t *pd_context = (internal_lvds_context_t *)context;
+	pd_attr_t      *tattr      = NULL;  /* holds time delay b/ pwr transition */
+	unsigned long            delay = 0, delay1;
+
+	PD_DEBUG("state = %lu", state);
+
+	PD_DEBUG("internal_lvds_set_power() to state = %lu\n",state);
+	/* Basic parameter check */
+	if (!context) {
+		return PD_ERR_NULL_PTR;
+	}
+
+	/* Check for invalid state */
+	if (state > PD_POWER_MODE_D3) {
+		return PD_ERR_INVALID_POWER;
+	}
+
+	/* Get the index into above table */
+	if (state == PD_POWER_MODE_D0) {
+		i = 0;
+	} else {
+		i = 1;
+	}
+
+	internal_lvds_write_reg(pd_context, 0x61204, 0xABCD0000, 0xFFFFFFFF, PD_REG_MIO);
+
+	/* Program panel power up/down delays: Either T1/T2 or T3/T4*/
+	tattr = pd_get_attr(pd_context->attr_list,
+		pd_context->num_attrs, table_set_power[i].id1, 0);
+	/* Convert ms to 100us */
+	delay1 = tattr->current_value;
+	delay = (tattr->current_value * 10) << 16;
+	tattr = pd_get_attr(pd_context->attr_list,
+		pd_context->num_attrs, table_set_power[i].id2, 0);
+	delay1 += tattr->current_value;
+	delay |= tattr->current_value * 10;
+
+	internal_lvds_write_reg(pd_context, table_set_power[i].reg, delay, 0x1FFF1FFF, PD_REG_MIO);
+
+	/* Program power cycle delay: convert ms to 100ms */
+	delay = pd_get_attr(pd_context->attr_list,
+		pd_context->num_attrs, PD_ATTR_ID_FP_PWR_T5, 0)->current_value;
+	delay1 += delay;
+	/* TODO: Write reference divider [31:8] */
+	delay = ((delay/100+1) & 0xFF) | ((pd_context->gfx_freq*100/2-1)<<8);
+	internal_lvds_write_reg(pd_context, 0x61210, delay, 0xFFFFFFFF, PD_REG_MIO);
+
+	/* Power state target */
+	internal_lvds_write_reg(pd_context, 0x61204, table_set_power[i].bit, BIT(0), PD_REG_MIO);
+
+	/* Power down on reset available on crestline onwards */
+		internal_lvds_write_reg(pd_context, 0x61204, BIT(1), BIT(1), PD_REG_MIO);
+
+/* Make this a compile time so that size of vBIOS doesn't become > 64KB */
+#if defined(CONFIG_PLB) || defined(CONFIG_TNC)
+	/* PWM is a method of controlling the backlight intensity.
+	 * It is not method to turn on baclkight.
+	 * We still need the PD method to turn on the backlight.
+	 *
+	 * This feature is for Pouslbo Only. We check that the user has set the
+	 * inverter frequency. Default intensity, if not set, is 100%
+	 *
+	 * Due to the high amount of calculation, we want to only set this register
+	 * if it has not been ser previously. The register could be
+	 * "brought forward" from VBIOS.
+	 */
+	if(pd_context->inverter_freq != 0xFFFF &&  /* Overwritten by set_attr */
+		(pd_context->chipset == PCI_DEVICE_ID_VGA_PLB ||
+		 pd_context->chipset == PCI_DEVICE_ID_VGA_TNC ||
+		 pd_context->chipset == PCI_DEVICE_ID_VGA_TNC_A0 ||
+		 pd_context->chipset == PCI_DEVICE_ID_VGA_LNC) &&
+		 !pd_context->pwm_done) {
+		unsigned long reg_value = 0;
+		unsigned long percentage = 0;
+		unsigned long calculation = 0;
+		unsigned long blc_pwm_ctl2 = 0;
+
+		/* We first need to get the graphics frequency, which will be used to
+		 * calculate Backlight Modulation Frequency[BMF]. BMF will be used to
+		 * fill up the 15 MSB in the 0x61254 register
+		 *
+		 * The calculation for the Modulation Frequency field in the
+		 * BLC_PWM_CTL Register is:
+		 *
+         *     Reference Clock Freq               1
+         *     -----------------------   x    ------------------
+         *            Divider                   PWM Freq in Hz
+		 *
+		 */
+#if 0
+		/* GMA accurate calculation that requires "calculation" to be an
+		 * unsigned long long typedef */
+		calculation = pd_context->gfx_freq * PWM_FREQ_CALC_CONSTANT_2;
+		calculation = calculation / 0x20; /*pouslbo specific divider*/
+		calculation = calculation * PWM_FREQ_CALC_CONSTANT_1;
+		calculation = calculation / pd_context->inverter_freq;
+		calculation = calculation / PWM_FREQ_CALC_CONSTANT_1;
+#endif
+		/* Some system bios cannot take 64 bit data type. Using a more
+		 * simplified calculation that is not too accurate if the inputs
+		 * are not round numbers */
+		calculation = pd_context->inverter_freq * 0x20; /* plb/tnc divider */
+		calculation = (pd_context->gfx_freq * PWM_FREQ_CALC_CONSTANT_2) /
+			calculation;
+
+		/* Writing the register: 15 MSB is the max lvds clock / 32.
+		* Bit 16 can either be legacy or non legacy depending upon Attr #72. */
+		if (pd_context->gn4_plus) {
+			blc_pwm_ctl2 = (1L << 31) |
+				(pd_context->blm_legacy_mode << 30) |
+				((pd_context->pipe == PD_SET_MODE_PIPE_B)?1L:0L << 29);
+			internal_lvds_write_reg(pd_context, 0x61250, blc_pwm_ctl2, 0xFFFFFFFF, PD_REG_MIO);
+			reg_value = (calculation & 0xFFFF)<<16;
+		} else {
+			reg_value = ((calculation & 0xFFFE) |
+				pd_context->blm_legacy_mode)<<16;
+		}
+
+		/* The 16 LSB is a value that the user sets in configuration.
+		 * user sets the value in percentage.
+		 * We convert it into the clock speed */
+		percentage = ( pd_context->pwm_intensity * (unsigned long)calculation);
+		reg_value |= (unsigned long)( percentage / (int)100 ) & 0xFFFE;
+		internal_lvds_write_reg(pd_context, 0x61254, reg_value, 0xFFFFFFFF, PD_REG_MIO);
+
+		/* set the flag so that we only do this function once */
+		pd_context->pwm_done = 1;
+	}
+#endif
+
+	if (state != PD_POWER_MODE_D0) {
+		/* Wait until the current power up/down sequence is complete */
+		i = 0;
+		while(internal_lvds_read_reg(pd_context, 0x61200, PD_REG_MIO) & 0x80000000L) {
+			i++;
+			if(i > 0x100000L) {
+				break;
+			}
+		}
+		internal_lvds_write_reg(pd_context, 0x61180, 0, BIT(31), PD_REG_MIO);
+		//pd_usleep(delay1*1000);	
+	}
+
+#ifdef CONFIG_TNC
+#if 0
+
+/*-----------------------------------------------------------------------------
+ * LPC Register Offsets. Used for LVDS BKLT control. Registers are part
+ * Atom E6xx [D31:F0]
+ ----------------------------------------------------------------------------*/
+#define RGEN    0x20
+#define RGIO    0x24
+#define RGLVL   0x28
+#define TNC_LVDS_VDDEN	 BIT(0)
+#define TNC_LVDS_BKLTEN  BIT(1)
+#define TNC_LVDS_BKLTCTL BIT(2) 
+
+	if (pd_context->chipset == PCI_DEVICE_ID_VGA_TNC ||
+		pd_context->chipset == PCI_DEVICE_ID_VGA_TNC_A0 ||
+		pd_context->chipset == PCI_DEVICE_ID_VGA_LNC) {
+		unsigned long value;
+
+		/* Enable backlight for LVDS: based on observed si behavior:
+		 * Subject to change based on si DE feedback */
+		if (state == PD_POWER_MODE_D0) {
+			value = TNC_LVDS_BKLTCTL|TNC_LVDS_BKLTEN|TNC_LVDS_BKLTCTL;
+		} else {
+			value = 0;
+		}
+		internal_lvds_write_reg(pd_context, RGEN, value,			 
+			TNC_LVDS_BKLTCTL|TNC_LVDS_BKLTEN|TNC_LVDS_BKLTCTL, PD_REG_LPC);
+		internal_lvds_write_reg(pd_context, RGIO, value,
+			TNC_LVDS_BKLTCTL|TNC_LVDS_BKLTEN|TNC_LVDS_BKLTCTL, PD_REG_LPC);
+	}
+#endif
+#endif
+
+	/* update power state */
+	pd_context->power_state = state;
+	return PD_SUCCESS;
+}                                                         /* internal_lvds_set_power */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_get_power
+ *
+ * Description:
+ *   Returns the current LVDS power state back to the caller.
+ *
+ * Parameters:
+ *    [IN] context: device context to extract information from
+ *    [OUT] state:  current power state
+ *
+ * Return:
+ *    PD_ERR_NULL_PTR:      if one of the parameters is invalid
+ *    PD_SUCCESS:           if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int internal_lvds_get_power (void *context, unsigned long *state)
+{                                                         /* internal_lvds_get_power */
+	if ((NULL == context) || (NULL == state)) {
+		return PD_ERR_NULL_PTR;
+	}
+	PD_DEBUG("internal_lvds_get_power()\n");
+	/* The caller should be able to do this himself, but whatever */
+	*state = ((internal_lvds_context_t *) context)->power_state;
+	return PD_SUCCESS;
+}                                                         /* internal_lvds_get_power */
+
+int internal_lvds_save(void *context, void **state, unsigned long flags)
+{
+	*state = NULL;
+	return PD_SUCCESS;
+}
+
+int internal_lvds_restore(void *context, void *state, unsigned long flags)
+{
+	int ret = PD_SUCCESS;
+	return ret;
+}
+
+/*----------------------------------------------------------------------
+ * Function: internal_lvds_get_port_status()
+ *
+ * Description:  It is called to get the information about the display
+ *
+ * Parameters:  context - Port driver's context
+ *				port_status - Returns the display type and connection state
+ *
+ * Return:      PD_SUCCESS(0)  success
+ *              PD_ERR_XXXXXX  otherwise
+ *----------------------------------------------------------------------*/
+int internal_lvds_get_port_status(void *context, pd_port_status_t *port_status)
+{
+	/* Display connection cannot be determined */
+	port_status->display_type = PD_DISPLAY_LVDS_INT;
+	port_status->connected    = PD_DISP_STATUS_UNKNOWN;
+	return PD_SUCCESS;
+}
+
+static unsigned long internal_lvds_read_reg(internal_lvds_context_t *pd_context,unsigned long reg,
+	unsigned long reg_type)
+{
+	pd_reg_t list[2];
+	int ret;
+
+	list[0].reg = reg;
+	list[0].value = 0;
+	list[1].reg = PD_REG_LIST_END;
+	ret = pd_context->callback->read_regs(
+		pd_context->callback->callback_context, list, reg_type);
+	if (ret) {
+		PD_ERROR("LVDS read regs: Failed.");
+	}
+	return list[0].value;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_write_reg
+ *
+ * Description:
+ *    Writes bits in "value" into a register.  Bits written are dictated by
+ *    the "change_bits" mask.
+ *
+ * Parameters:
+ *    [IN] pd_context:  device context, dispatcher to the actual write_reg
+ *                      function
+ *    [IN] reg:  register to write value to
+ *    [IN] value:  value to change the register to
+ *    [IN] change_bits:  bit mask, the bits set to "1" will be modified by
+ *                       the corresponding bits in "value"
+ *
+ * Return:
+ *    None
+ *
+ *----------------------------------------------------------------------------
+ */
+static void internal_lvds_write_reg(internal_lvds_context_t *pd_context, unsigned long reg,
+		unsigned long value,
+		unsigned long change_bits,
+		unsigned long reg_type)
+{                                                         /* internal_lvds_write_reg */
+	pd_reg_t list[2];
+	int ret;
+
+	list[0].reg = reg;
+	list[0].value = (internal_lvds_read_reg(pd_context, reg, PD_REG_MIO) & ~change_bits) | value;
+	list[1].reg = PD_REG_LIST_END;
+	ret = pd_context->callback->write_regs(
+		pd_context->callback->callback_context, list, reg_type);
+	if (ret) {
+		PD_ERROR("LVDS write regs: Failed.");
+	}
+	return;
+}                                                         /* internal_lvds_write_reg */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_panel_fit
+ *
+ * Description:
+ *    Enables panel fitting
+ *
+ * Parameters:
+ *    [IN] pd_context:  device context
+ *
+ * Return:
+ *    None
+ *
+ *----------------------------------------------------------------------------
+ */
+static void internal_lvds_panel_fit(internal_lvds_context_t *pd_context)
+{
+	/* enable auto vertical ratio */
+	/* enable auto horizantal ratio */
+	/* no dither */
+	unsigned long panel_fit_reg = 0x00000220;
+	PD_DEBUG("internal_lvds_panel_fit() \n");
+
+	PD_TRACE_ENTER;
+
+	if (pd_context->current_mode->width != pd_context->fp_width ||
+		pd_context->current_mode->height != pd_context->fp_height) {
+		/* Enable panel fitting */
+		/* vertical interpolation = bilinear */
+		/* horizontal interpolation = bilinear */
+		panel_fit_reg |= 0x80000440;
+	}
+	/* Enable dither based on default/user-set value:
+	 *   By default
+	 *        dither = 1 for 18-bit panels
+	 *               = 0 for 24-bit panels.
+	 *   But this behavior can be changed by setting the DITHER attribute.
+	 *        When user sets the attribute, dither will be updated
+	 *        as part of attribute processing in set attributes. */
+	/* For gn4 based chipsets dither is controlled in port_control register */
+	if (!pd_context->gn4_plus) {
+		/* Default behavior */
+		if (pd_context->panel_depth == 18) {
+			panel_fit_reg |= BIT(3);
+		}
+
+		/* Overwritten by set attribute */
+		if (pd_context->dither != 0xFFFF) {
+			if (pd_context->dither) {
+				panel_fit_reg |= BIT(3);
+			} else {
+				panel_fit_reg &= ~BIT(3);
+			}
+		}
+	}
+
+	if (pd_context->gn4_plus) {
+		unsigned long src_ratio, dest_ratio;
+		panel_fit_reg = 0;
+		if (pd_context->native_dtd &&
+			(pd_context->current_mode->width != pd_context->native_dtd->width ||
+			pd_context->current_mode->height !=
+				pd_context->native_dtd->height)) {
+			/* Enable panel fitter */
+			panel_fit_reg = 0x80000000;
+
+			/* Select the pipe */
+			if (pd_context->pipe & PD_SET_MODE_PIPE_B) {
+				panel_fit_reg |= BIT(29);   /* bits[30:29] = 01 for pipe B */
+			}
+
+			/* Scaling mode:
+			 *    Default - Auto scaling src_ratio == dest_ratio
+			 *    Piller box scaling - src_ratio < dest_ratio
+			 *    Letter box scaling - src_ratio > dest_ratio */
+
+			/* To make this work correctly, port driver shall know the
+			 * size of the framebuffer, not the src mode. Most of the
+			 * times the src mode is fb, but not all the cases.
+			 * User has an attribute to change
+			 *    1. Between Pillerbox and auto, and vice versa
+			 *                and
+			 *    2. Between Letterbox and auto, and vice versa.
+			 */
+			if (pd_context->aspect_ratio) {
+				src_ratio = (pd_context->current_mode->width << 10)/
+					(pd_context->current_mode->height);
+				dest_ratio = (pd_context->native_dtd->width << 10)/
+					(pd_context->native_dtd->height);
+
+				if (dest_ratio > src_ratio) {
+					/* Pillarbox scaling */
+					panel_fit_reg |= BIT(27);
+				} else if (dest_ratio < src_ratio) {
+					/* Letterbox scaling */
+					panel_fit_reg |= BIT(27) | BIT(26);
+				}
+			}
+
+			/* Filter coefficient select: pd_context->text_tune = 0,1,2 */
+			panel_fit_reg |= (pd_context->text_tune << 24);
+		}
+	}
+
+	internal_lvds_write_reg(pd_context, 0x61230, panel_fit_reg, 0xFFFFFFFF, PD_REG_MIO);
+	PD_DEBUG("panel_fit_reg 0x61230 = 0x%lx", panel_fit_reg);
+}
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: internal_lvds_get_dclk
+ *
+ * Description:
+ *    Gets the Dclk for LVDS
+ *
+ * Parameters:
+ *    [IN] pd_context:  device context
+ *	  [OUT]internal_lvds_info:   Structure that contains the min and max dclk
+ *
+ * Return:
+ *    None
+ *
+ *----------------------------------------------------------------------------
+ */
+static void internal_lvds_get_dclk(internal_lvds_context_t *pd_context, pd_dvo_info_t *internal_lvds_info )
+{
+	PD_DEBUG("internal_lvds_get_dclk()\n");
+	/* Get the min and max dclks for lvds */
+	if (pd_context->dual_channel) {
+		internal_lvds_info->min_dclk = LVDS_MIN_DCLK * 2 ;
+		internal_lvds_info->max_dclk = LVDS_MAX_DCLK * 2;
+	} else {
+		internal_lvds_info->min_dclk = LVDS_MIN_DCLK;
+		internal_lvds_info->max_dclk = LVDS_MAX_DCLK;
+	}
+	PD_DEBUG("internal_lvds_dclk: #1\n");
+/* This #define is the result of code size reduction effort. */
+#ifdef CONFIG_CTG
+	/* Set dclk for GM965 */
+	if(pd_context->chipset==PCI_DEVICE_ID_VGA_CTG){
+		/* Set dclk for GM965/CTG */
+		if (pd_context->dual_channel) {
+			internal_lvds_info->min_dclk = LVDS_GM965_DUAL_MIN_DCLK ;
+			internal_lvds_info->max_dclk = LVDS_GM965_DUAL_MAX_DCLK;
+		} else {
+			internal_lvds_info->min_dclk = LVDS_GM965_SINGLE_MIN_DCLK;
+			internal_lvds_info->max_dclk = LVDS_GM965_SINGLE_MAX_DCLK;
+		}
+	}
+#else
+
+	/* Set dclk for 915GM */
+	if(pd_context->chipset==PCI_DEVICE_ID_VGA_915AL){
+		if (pd_context->dual_channel) {
+			internal_lvds_info->min_dclk = LVDS_915GM_DUAL_MIN_DCLK ;
+			internal_lvds_info->max_dclk = LVDS_915GM_DUAL_MAX_DCLK;
+		} else {
+			internal_lvds_info->min_dclk = LVDS_915GM_SINGLE_MIN_DCLK;
+			internal_lvds_info->max_dclk = LVDS_915GM_SINGLE_MAX_DCLK;
+		}
+	} else if(pd_context->chipset==PCI_DEVICE_ID_VGA_945GM ||
+				pd_context->chipset==PCI_DEVICE_ID_VGA_945GME){
+		/* Set dclk for 945GM */
+		if (pd_context->dual_channel) {
+			internal_lvds_info->min_dclk = LVDS_945GM_DUAL_MIN_DCLK ;
+			internal_lvds_info->max_dclk = LVDS_945GM_DUAL_MAX_DCLK;
+		} else {
+			internal_lvds_info->min_dclk = LVDS_945GM_SINGLE_MIN_DCLK;
+			internal_lvds_info->max_dclk = LVDS_945GM_SINGLE_MAX_DCLK;
+		}
+	} else if(pd_context->chipset==PCI_DEVICE_ID_VGA_GM965 ||
+				pd_context->chipset==PCI_DEVICE_ID_VGA_GME965){
+		/* Set dclk for GM965 */
+		if (pd_context->dual_channel) {
+			internal_lvds_info->min_dclk = LVDS_GM965_DUAL_MIN_DCLK ;
+			internal_lvds_info->max_dclk = LVDS_GM965_DUAL_MAX_DCLK;
+		} else {
+			internal_lvds_info->min_dclk = LVDS_GM965_SINGLE_MIN_DCLK;
+			internal_lvds_info->max_dclk = LVDS_GM965_SINGLE_MAX_DCLK;
+		}
+	}
+#endif
+
+#ifdef CONFIG_TNC
+	/* Get the min and max dclks for Atom E6xx lvds */
+	if ((pd_context->chipset == PCI_DEVICE_ID_VGA_TNC) ||
+	    (pd_context->chipset == PCI_DEVICE_ID_VGA_TNC_A0) ||
+	    (pd_context->chipset == PCI_DEVICE_ID_VGA_LNC)) {
+		internal_lvds_info->min_dclk = LVDS_TNC_SINGLE_MIN_DCLK;
+		/* Experimental feature to raise TC LVDS clk to 110MHz. */
+		if (pd_context->tc_110MHz_clk) {
+			internal_lvds_info->max_dclk = 110000L;
+		} else {
+			internal_lvds_info->max_dclk = LVDS_TNC_SINGLE_MAX_DCLK;
+		}
+		PD_DEBUG("internal_lvds_dclk: #2\n");
+	}
+#endif
+	PD_DEBUG("internal_lvds_dclk: at the end\n");
+}
+
+#pragma optimize ("",on)
diff --git a/drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.h b/drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.h
new file mode 100644
index 0000000..f691d1a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/ch7036/lvds/lvds.h
@@ -0,0 +1,170 @@
+/* -*- pse-c -*-
+ *-----------------------------------------------------------------------------
+ * Filename: lvds.h
+ * $Revision: 1.3 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is header file for Internal LVDS PORT DRIVER.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PD_LVDS_H
+#define _PD_LVDS_H
+
+#include <pd.h>
+
+#ifdef T_LINUX 
+#include <pci.h>
+#endif
+
+/* Values received from DPG hardware engineer. These are for single channel.  */
+
+#ifndef PCI_DEVICE_ID_VGA_855
+#define PCI_DEVICE_ID_VGA_855      0x3582
+#endif
+#ifndef PCI_DEVICE_ID_VGA_915AL
+#define PCI_DEVICE_ID_VGA_915AL    0x2592
+#endif
+#ifndef PCI_DEVICE_ID_VGA_945GM
+#define PCI_DEVICE_ID_VGA_945GM    0x27A2
+#endif
+#ifndef PCI_DEVICE_ID_VGA_945GME
+#define PCI_DEVICE_ID_VGA_945GME   0x27AE
+#endif
+#ifndef PCI_DEVICE_ID_VGA_GM965
+#define PCI_DEVICE_ID_VGA_GM965    0x2A02
+#endif
+#ifndef PCI_DEVICE_ID_VGA_GME965
+#define PCI_DEVICE_ID_VGA_GME965   0x2A12
+#endif
+#ifndef PCI_DEVICE_ID_VGA_CTG
+#define PCI_DEVICE_ID_VGA_CTG      0x2A42
+#endif
+#ifndef PCI_DEVICE_ID_VGA_PLB
+#define PCI_DEVICE_ID_VGA_PLB      0x8108
+#endif
+#ifndef PCI_DEVICE_ID_VGA_PNVM
+#define PCI_DEVICE_ID_VGA_PNVM     0xA011
+#endif
+#ifndef PCI_DEVICE_ID_VGA_TNC
+#define PCI_DEVICE_ID_VGA_TNC      0x4108
+#endif
+#ifndef PCI_DEVICE_ID_VGA_TNC_A0
+#define PCI_DEVICE_ID_VGA_TNC_A0   0x4100
+#endif
+#ifndef PCI_DEVICE_ID_VGA_LNC
+#define PCI_DEVICE_ID_VGA_LNC      0x4102
+#endif
+
+
+#define LVDS_MIN_DCLK 12000L    /* in KHz */
+#define LVDS_MAX_DCLK 112000L   /* in KHz */
+/* definition for 915GM */
+#define LVDS_915GM_SINGLE_MIN_DCLK   20000L
+#define LVDS_915GM_SINGLE_MAX_DCLK  112000L
+#define LVDS_915GM_DUAL_MIN_DCLK     25000L
+#define LVDS_915GM_DUAL_MAX_DCLK    224000L
+
+/* definition for 945GM */
+#define LVDS_945GM_SINGLE_MIN_DCLK   25000L
+#define LVDS_945GM_SINGLE_MAX_DCLK  112000L
+#define LVDS_945GM_DUAL_MIN_DCLK     25000L
+#define LVDS_945GM_DUAL_MAX_DCLK    224000L
+
+/* definition for GM965 */
+#define LVDS_GM965_SINGLE_MIN_DCLK   25000L
+#define LVDS_GM965_SINGLE_MAX_DCLK  112000L
+#define LVDS_GM965_DUAL_MIN_DCLK     25000L
+#define LVDS_GM965_DUAL_MAX_DCLK    224000L
+
+/* definition for Atom E6xx */
+#define LVDS_TNC_SINGLE_MIN_DCLK     19750L
+#define LVDS_TNC_SINGLE_MAX_DCLK     79500L
+
+#define LVDS_MIN(a, b)       ((a)<(b)?(a):(b))
+
+/* Local attributes
+ * BIT15 of attribute Id specifies that it is a local attribute */
+#define LVDS_ATTR_ID_DATA_FORMAT   (BIT(15)|1)
+#define LVDS_ATTR_ID_TC_LVDS_CLK   (BIT(15)|2)
+
+/* Default values */
+#define LVDS_DEF_PANEL_DEPTH    18      /* Default panel depth */
+#define LVDS_DEF_DITHER          1      /* default=1 as default panel depth=18*/
+#define LVDS_DEF_SCALE_ON        1      /* Default scaling is on */
+#define LVDS_DEF_PANEL_FIT       1      /* Default panel fit in on */
+
+typedef struct _internal_lvds_context {
+	unsigned short fp_width;
+	unsigned short fp_height;
+	unsigned short dual_channel;
+	unsigned short panel_type;
+	unsigned short panel_fit;
+	unsigned short panel_depth;
+	unsigned short dither;
+	unsigned short aspect_ratio;
+	unsigned long  text_tune;
+	unsigned long  pwm_intensity;
+	unsigned long  inverter_freq;
+	unsigned long  blm_legacy_mode;
+
+	unsigned long power_state;
+	unsigned short chipset;
+	unsigned char init_done;
+	unsigned char num_attrs;
+	unsigned long pipe;
+	unsigned short gfx_freq;
+	unsigned char gn4_plus;
+	unsigned char pwm_done;
+	unsigned char tc_110MHz_clk;
+
+	pd_callback_t *callback;
+	pd_timing_t   *timing_table;
+	pd_attr_t     *attr_list;
+	pd_timing_t   *native_dtd;
+	pd_timing_t   *current_mode;
+} internal_lvds_context_t;
+
+extern int PD_MODULE_INIT(internal_lvds_init, (void *handle));
+extern int PD_MODULE_EXIT(internal_lvds_exit, (void));
+extern unsigned long internal_lvds_validate(unsigned long cookie);
+extern int internal_lvds_open(pd_callback_t *callback, void **context);
+extern int internal_lvds_init_device(void *context);
+extern int internal_lvds_close(void *context);
+extern int internal_lvds_set_mode(void *context, pd_timing_t *mode,
+			unsigned long flags);
+extern int internal_lvds_post_set_mode(void *context, pd_timing_t *mode,
+			unsigned long flags);
+extern int internal_lvds_set_attrs(void *context, unsigned long num, pd_attr_t *list);
+extern int internal_lvds_get_attrs(void *context, unsigned long*num, pd_attr_t **list);
+extern int internal_lvds_get_timing_list(void *context, pd_timing_t *in_list,
+			pd_timing_t **list);
+extern int internal_lvds_set_power(void *context, unsigned long state);
+extern int internal_lvds_get_power(void *context, unsigned long *state);
+extern int internal_lvds_save(void *context, void **state, unsigned long flags);
+extern int internal_lvds_restore(void *context, void *state, unsigned long flags);
+extern int internal_lvds_get_port_status(void *context, pd_port_status_t *port_status);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/lpd/lpd.c b/drivers/gpu/drm/emgd/emgd/pal/lpd/lpd.c
new file mode 100644
index 0000000..a180772
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/lpd/lpd.c
@@ -0,0 +1,114 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: lpd.c
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Functions necessary to allow debug printing from the port drivers.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.dpd
+
+#include <igd_pd.h>
+#include <igd_pi.h>
+#include "pd_print.h"
+#include <memory.h>
+
+
+/*
+ * This file implements the pd debug printing functions using the OAL.
+ * In order to keep the OAL debug printing macro definitions in the OAL
+ * the DEBUG_BUILD_TYPE option must be set, even in a production build. The
+ * port drivers themselves must not call the pd debug printing functions
+ * in a release build. This enables the PD SDK to have debug printing from
+ * port drivers, even when using a release driver.
+ */
+#ifndef DEBUG_BUILD_TYPE
+#define DEBUG_BUILD_TYPE
+#endif
+#define MODULE_NAME hal.dpd
+
+#include <io.h>
+#include <igd_debug.h>
+
+unsigned long *dropped_debug_messages;
+
+int pd_set_funcname( const char *name )
+{
+	os_set_funcname(name);
+	return 1;
+}
+
+int pd_print(const char *funcname, const int error,
+	const int error_exit, const char *format, ...)
+{
+#ifdef DEBUG_BUILD_TYPE
+	va_list ap;
+	unsigned int *blah;
+	char *priority = error ? KERN_ERR : EMGD_DEBUG_MSG_PRIORITY;
+	char *fmt = NULL;
+
+	/* Can't directly use the EMGD_DEBUG_S macro (because "format" is a string
+	 * variable), so duplicate some of it here:
+	 */
+	if (!(emgd_debug && emgd_debug-> MODULE_NAME)) {
+		return 0;
+	}
+
+	va_start(ap, format);
+	blah = (unsigned int *)ap;
+
+	if (error_exit) {
+		EMGD_DEBUG("EXIT With Error...");
+	}
+
+	/* Create a new format string, with all of the correct parts: */
+	fmt = OS_ALLOC(strlen(priority) + strlen(funcname) +
+		strlen(format) + 2);
+	if (fmt == NULL) {
+		printk(format, blah[0], blah[1], blah[2], blah[3], blah[4], blah[5],
+			blah[6], blah[7], blah[8], blah[9]);
+	} else {
+		sprintf(fmt, "%s%s %s", priority, funcname, format);
+		printk(fmt, blah[0], blah[1], blah[2], blah[3], blah[4], blah[5],
+			blah[6], blah[7], blah[8], blah[9]);
+		OS_FREE(fmt);
+	}
+	printk("\n");
+	va_end(ap);
+
+	return 0;
+#endif
+}
+
+void pd_trace_enter(const char *funcname)
+{
+	EMGD_DEBUG_S("%s ENTER", funcname);
+}
+
+void pd_trace_exit(const char *funcname)
+{
+	EMGD_DEBUG_S("%s EXIT", funcname);
+}
diff --git a/drivers/gpu/drm/emgd/emgd/pal/lpd/pd_print.h b/drivers/gpu/drm/emgd/emgd/pal/lpd/pd_print.h
new file mode 100644
index 0000000..8893e1b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/lpd/pd_print.h
@@ -0,0 +1,65 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pd_print.h
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Header file to get printing macros for port drivers
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PD_PRINT_H
+#define _PD_PRINT_H
+
+#include <config.h>
+
+extern int pd_print(const char *funcname, const int error,
+	const int error_exit, const char *format, ...);
+extern void pd_trace_enter(const char *funcname);
+extern void pd_trace_exit(const char *funcname);
+
+#ifdef DEBUG_BUILD_TYPE
+#define PD_DEBUG(arg...) pd_print(__FUNCTION__, 0, 0, arg)
+#define PD_ERROR(arg...) pd_print(__FUNCTION__, 1, 0, arg)
+#define PD_TRACE_ENTER   pd_trace_enter(__FUNCTION__)
+#define PD_TRACE_EXIT    pd_trace_exit(__FUNCTION__)
+#define PD_ERROR_EXIT(arg...) pd_print(__FUNCTION__, 1, 1, arg)
+#else
+#define PD_DEBUG(arg...)
+#define PD_ERROR(arg...)
+#define PD_TRACE_ENTER
+#define PD_TRACE_EXIT
+#define PD_ERROR_EXIT(arg...)
+#endif
+
+#define PD_OFFSETOF(t,m) ((unsigned long)&(((t *)0)->m))
+#if 0
+#define PD_OFFSETOF(t,m) offsetof(t,m)
+#endif
+
+#define PD_MODULE_INIT(func, params) func params
+#define PD_MODULE_EXIT(func, params) func params
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.c b/drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.c
new file mode 100644
index 0000000..b67a992
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.c
@@ -0,0 +1,1555 @@
+/*
+ *-----------------------------------------------------------------------------
+ * 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 <config.h>
+#include <igd_pd.h>
+#include <pd.h>
+#include <pd_print.h>
+
+#include "lvds.h"
+
+/* One space between the #define and the backslash,else compilers complain */
+#define PTR_OFFSET_UCHAR(ptr,offset)   (*((unsigned char *)ptr + offset))
+#define PTR_OFFSET_USHORT(ptr, offset) (*(unsigned short *)((unsigned char *)ptr + offset))
+
+#define PTR_OFFSET_ULONG(ptr, offset) (*(unsigned long *)((unsigned char *)ptr + offset))
+/* END OF OPTIMIZATION MACROS */
+
+/* This constant = 10,000,000.  The value is used to
+ * get effective results from the integer math, and
+ * to not divide by 0. */
+#define PWM_FREQ_CALC_CONSTANT_1        0x00989680
+/* This constant is 1,000,000 - to multiply to get
+ * the Display Clock Frequency to the order of Mhz */
+#define PWM_FREQ_CALC_CONSTANT_2        0x000F4240
+
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(p) (sizeof(p)/sizeof((p)[0]))
+#endif
+
+static pd_version_t  lvds_version = {11, 0, 0, 0}; /* driver version */
+static unsigned long lvds_dab_list[] = {
+	PD_DAB_LIST_END
+}; /* dab list */
+
+static unsigned long supported_chipset[] =
+{
+#ifdef CONFIG_855
+	PCI_DEVICE_ID_VGA_855,
+#endif
+#ifdef CONFIG_915AL
+	PCI_DEVICE_ID_VGA_915AL,
+#endif
+#ifdef CONFIG_945GM
+	PCI_DEVICE_ID_VGA_945GM,
+	PCI_DEVICE_ID_VGA_945GME,
+#endif
+#ifdef CONFIG_965GM
+	PCI_DEVICE_ID_VGA_GM965,
+	PCI_DEVICE_ID_VGA_GME965,
+#endif
+#ifdef CONFIG_CTG
+	PCI_DEVICE_ID_VGA_CTG,
+#endif
+#ifdef CONFIG_PLB
+	PCI_DEVICE_ID_VGA_PLB,
+#endif
+#ifdef CONFIG_TNC
+	PCI_DEVICE_ID_VGA_TNC,
+	PCI_DEVICE_ID_VGA_TNC_A0,
+	PCI_DEVICE_ID_VGA_LNC,
+#endif
+};
+
+static pd_driver_t  lvds_driver  = {
+	PD_SDK_VERSION,
+	"Internal LVDS Port Driver",
+	0,
+	&lvds_version,
+	PD_DISPLAY_LVDS_INT,
+	PD_FLAG_UP_SCALING,
+	lvds_dab_list,
+	100,
+	lvds_validate,
+	lvds_open,
+	lvds_init_device,
+	lvds_close,
+	lvds_set_mode,
+	lvds_post_set_mode,
+	lvds_set_attrs,
+	lvds_get_attrs,
+	lvds_get_timing_list,
+	lvds_set_power,
+	lvds_get_power,
+	lvds_save,
+	lvds_restore,
+	lvds_get_port_status
+};
+
+/* This is a common attribute table for all chipsets. At the end of the table
+ * there are multiple end entries to add chipset specific attributes.
+ * Chipset specific attributes:
+ *     965GM/GM45- Maintain aspect ratio
+ * Note:
+ *    1. Make sure to update the chipset_attr_index whenever adding a
+ *       chipset specific new attr.
+ */
+static pd_attr_t lvds_attrs[] =
+{
+	/* Range attributes */
+
+	/*<-------ID----------->              <----TYPE-------->  <---NAME----->  <----flag---->               <---DEF_VAL---->       <--CURR_VALUE-->      min max  st */
+	PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T1,   PD_ATTR_TYPE_RANGE, "FP Power T1",  PD_ATTR_FLAG_USER_INVISIBLE, 0,                     0,                    0,  819,  1),
+	PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T2,   PD_ATTR_TYPE_RANGE, "FP Power T2",  PD_ATTR_FLAG_USER_INVISIBLE, 0,                     0,                    0,  819,  1),
+	PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T3,   PD_ATTR_TYPE_RANGE, "FP Power T3",  PD_ATTR_FLAG_USER_INVISIBLE, 0,                     0,                    0,  819,  1),
+	PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T4,   PD_ATTR_TYPE_RANGE, "FP Power T4",  PD_ATTR_FLAG_USER_INVISIBLE, 0,                     0,                    0,  819,  1),
+	PD_MAKE_ATTR (PD_ATTR_ID_FP_PWR_T5,   PD_ATTR_TYPE_RANGE, "FP Power T5",  PD_ATTR_FLAG_USER_INVISIBLE, 400,                 400,                    0,  3000, 1),
+	PD_MAKE_ATTR (PD_ATTR_ID_PANEL_DEPTH, PD_ATTR_TYPE_RANGE, "Panel Depth",  PD_ATTR_FLAG_USER_INVISIBLE, LVDS_DEF_PANEL_DEPTH,  LVDS_DEF_PANEL_DEPTH, 18, 24,   6),
+
+	PD_MAKE_ATTR (PD_ATTR_ID_PWM_INTENSITY,	  PD_ATTR_TYPE_RANGE, "PWM cycle",			  PD_ATTR_FLAG_USER_INVISIBLE,		100,		0,				  0,  100,  0),
+	PD_MAKE_ATTR (PD_ATTR_ID_INVERTER_FREQ,	  PD_ATTR_TYPE_RANGE, "Inverter Frequency",	  PD_ATTR_FLAG_USER_INVISIBLE,		100,		0,				  0,  0,  0),
+	PD_MAKE_ATTR (PD_ATTR_ID_BLM_LEGACY_MODE, PD_ATTR_TYPE_BOOL,  "Backlight Legacy mode",	  PD_ATTR_FLAG_USER_INVISIBLE,		0,		0,					  0,  0,  0),
+
+	/*<-------ID------------>                 <----TYPE--------> <---NAME----->        <------flag--------------->  <---DEF_VAL---->   <--CURR_VALUE-->   <---pad--> */
+	PD_MAKE_ATTR (PD_ATTR_ID_2_CHANNEL_PANEL, PD_ATTR_TYPE_BOOL, "Dual-channel panel", PD_ATTR_FLAG_USER_INVISIBLE, 0,                 0,                 0, 0, 0),
+	PD_MAKE_ATTR (PD_ATTR_ID_LVDS_PANEL_TYPE, PD_ATTR_TYPE_BOOL, "Panel Type",         PD_ATTR_FLAG_USER_INVISIBLE, 0,                 0,                 0, 0, 0),
+	PD_MAKE_ATTR (PD_ATTR_ID_PANEL_FIT,       PD_ATTR_TYPE_BOOL, "Panel Upscale",      PD_ATTR_FLAG_USER_INVISIBLE, LVDS_DEF_PANEL_FIT,LVDS_DEF_PANEL_FIT,0, 0, 0),
+	PD_MAKE_ATTR (PD_ATTR_ID_DITHER,          PD_ATTR_TYPE_BOOL, "Dither",             PD_ATTR_FLAG_USER_INVISIBLE, LVDS_DEF_DITHER,   LVDS_DEF_DITHER,   0, 0, 0),
+	PD_MAKE_ATTR (LVDS_ATTR_ID_TC_LVDS_CLK,   PD_ATTR_TYPE_BOOL, "TC LVDS CLK 110MHz", PD_ATTR_FLAG_USER_INVISIBLE, 0,                 0,                 0, 0, 0),
+
+	/* Start of chipset specific attributes */
+	/* Maintain aspect ratio */
+	PD_MAKE_ATTR (PD_ATTR_LIST_END,       0,                   "",            0,                           0,                0,               0,     0, 0),
+	/* Text tuning */
+	PD_MAKE_ATTR (PD_ATTR_LIST_END,       0,                   "",            0,                           0,                0,               0,     0, 0),
+
+	/* Attribute list end */
+	PD_MAKE_ATTR (PD_ATTR_LIST_END,       0,                   "",            0,                           0,                0,               0,     0, 0)
+};
+
+/* Rightnow it is -3 to reach starting of chipset specific attributes */
+static unsigned short chipset_attr_index = (unsigned short)
+	sizeof(lvds_attrs)/sizeof(pd_attr_t) - 3;
+
+static pd_attr_t lvds_965gm_attrs[] = {
+	PD_MAKE_ATTR (PD_ATTR_ID_MAINTAIN_ASPECT_RATIO,PD_ATTR_TYPE_BOOL,      "Maintain Aspect Ratio",0,             0,               0,               0,     0, 0),
+	PD_MAKE_ATTR (PD_ATTR_ID_TEXT_TUNING,          PD_ATTR_TYPE_RANGE,     "Text Enhancement",     0,             0,               0,               0,     2, 1),
+};
+
+static void lvds_write_reg(lvds_context_t *pd_context, unsigned long reg,
+		unsigned long value, unsigned long change_bits, unsigned long reg_type);
+
+static unsigned long lvds_read_reg(lvds_context_t *pd_context,
+		unsigned long reg, unsigned long reg_type);
+static void lvds_panel_fit(lvds_context_t *pd_context);
+
+static void lvds_get_dclk(lvds_context_t *pd_context, pd_dvo_info_t *lvds_info);
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: PD_MODULE_INIT(lvds_init)
+ *
+ * Description:
+ *    This is the entry function into LVDS port driver when
+ *    it first loads. This will call pd_register() to register
+ *    with Display driver.  Only the driver object is initialized in this
+ *    function, similar to DrverEntry() in a WDM driver.
+ *
+ * Parameters:
+ *    [OUT] *handle:  Not used.  Place holder for supporting dynamic pd
+ *
+ * Return:
+ *    PD_SUCCESS(0)  success
+ *    PD_ERR_XXXXXX  otherwise
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int PD_MODULE_INIT(lvds_init, (void *handle))
+{
+	/* register the LVDS driver */
+	return pd_register(handle, &lvds_driver);
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: PD_MODULE_EXIT(lvds_exit, (void))
+ *
+ * Description:
+ *    This function cleans up resources used by the LVDS driver
+ *
+ * Parameters:
+ *    None
+ *
+ * Return:
+ *    PD_SUCCESS(0):  always returns this
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int PD_MODULE_EXIT(lvds_exit, (void))
+{
+	return PD_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_validate
+ *
+ * Description:
+ *    Place holder for a future function
+ *
+ * Parameters:
+ *    TBD
+ *
+ * Return:
+ *    TBD
+ *
+ *----------------------------------------------------------------------------
+ */
+
+unsigned long lvds_validate (unsigned long cookie)
+{                                                          /* lvds_validate */
+	/* Validate magic cookie */
+	/* TODO: Implement the magic cookie algorithm */
+	return cookie;
+}                                                          /* lvds_validate */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_open
+ *
+ * Description:
+ *    This function creates an LVDS context and intialize it with LVDS
+ *    attributes.
+ *
+ *    Internal LVDS port is available only on MGM platform, this port driver
+ *    reads the GMCH device ID with pd_read_regs(PD_REG_PCI) to verify that
+ *    it is supported on the current platform.
+ *
+ * Parameters:
+ *    [IN] callback:    callback context
+ *    [INOUT] context:  Device context.  This function will set the attributes
+ *                      for this context, provided it is already allocated,
+ *                      i.e. not NULL.
+ *
+ * Return:
+ *    PD_ERR_NULL_PTR:  if either of the parameters is NULL
+ *    PD_ERR_NODEV:     if an LVDS device is already up and running
+ *    PD_ERR_NOMEM:     if a memory allocation failed
+ *    PD_SUCCESS:       if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/* lvds context structure being declared and initialized */
+
+static lvds_context_t lvds_context = {  /* lvds context structure */
+	0,                   /* fp_width     */
+	0,                   /* fp_height    */
+	0,                   /* dual_channel: Default single channel */
+	0,                   /* panel_type : 0-SPWG 1-OpenLDI*/
+	LVDS_DEF_PANEL_FIT,  /* panel_fit    */
+	LVDS_DEF_PANEL_DEPTH,/* panel_depth  */
+	0xFFFF,              /* dither       */
+	0,                   /* Main aspect ratio, default no */
+	0,                   /* panel filter: Default fuzzy filtering */
+	100,                 /* PWM Intensity */
+	0xFFFF,              /* Inverter Frequency*/
+	0,                   /* BLM Legacy Mode */
+
+	PD_POWER_MODE_D0,    /* power_state   */
+	0,                   /* chipset       */
+	0,                   /* init_done     */
+	0,                   /* num_attrs */
+	0,                   /* PIPE flags    */
+	0,                   /* Graphics Frequency */
+	0,                   /* is gn4 based LVDS controller? */
+	0,                   /* is pwm_done? */
+	0,                   /* is tc_110MHz_clk? i.e., TC max LVDS to 110MHz*/
+
+	NULL,                /* ptr to callback       */
+	NULL,                /* ptr to timing table   */
+	lvds_attrs,          /* ptr to attribute list */
+	NULL,                /* ptr to native timing  */
+	NULL,                /* current mode */
+};
+
+int lvds_open(pd_callback_t *callback, void **context)
+{                                                              /* lvds_open */
+	lvds_context_t *pd_context = (lvds_context_t*) &(lvds_context); /* static Global */
+	pd_reg_t reg_list[2];
+	int ret, i, valid_chipset = 0;
+	unsigned short chipset;
+
+	PD_TRACE_ENTER;
+
+
+
+	/* make sure parameters are valid */
+	if (!callback || !context) {
+		PD_ERROR("invalid parameter");
+		return (PD_ERR_NULL_PTR);
+	}
+	/* GMCH cannot support more than one device */
+	if (lvds_driver.num_devices > 0) {
+		return (PD_ERR_NODEV);
+	}
+	/* Verify that this is an GMCH with Internal LVDS available */
+	reg_list[0].reg = 2;
+	reg_list[1].reg = PD_REG_LIST_END;
+	ret = callback->read_regs(callback->callback_context, reg_list, PD_REG_PCI);
+	if(ret != PD_SUCCESS) {
+		return ret;
+	}
+	chipset = (unsigned short)(reg_list[0].value & 0xffff);
+	for (i = 0; i < ARRAY_SIZE(supported_chipset); i++) {
+		if (chipset == supported_chipset[i]){
+			valid_chipset = 1;
+			break;
+		}
+	}
+	if(!valid_chipset){
+		return PD_ERR_NODEV;
+	}
+
+	/* Special handling for gn4 and beyond chipsets */
+	if (chipset == PCI_DEVICE_ID_VGA_GM965 ||
+		chipset == PCI_DEVICE_ID_VGA_GME965 ||
+		chipset == PCI_DEVICE_ID_VGA_CTG ||
+		chipset == PCI_DEVICE_ID_VGA_TNC ||
+		chipset == PCI_DEVICE_ID_VGA_TNC_A0 ||
+		chipset == PCI_DEVICE_ID_VGA_LNC) {
+		lvds_context.gn4_plus = 1;
+	}
+
+	/* Initialize number of attributes */
+	/* +1 is to include the end attribute */
+	lvds_context.num_attrs = (unsigned char)chipset_attr_index + 1;
+
+	/* Add chipset specific attrbutes.
+	 * This can be expanded into a switch statement in future if required. */
+	if (lvds_context.gn4_plus) {
+		lvds_context.num_attrs += sizeof(lvds_965gm_attrs)/sizeof(pd_attr_t);
+		for (i=0; i < sizeof(lvds_965gm_attrs)/sizeof(pd_attr_t); i++) {
+			lvds_attrs[chipset_attr_index+i] = lvds_965gm_attrs[i];
+		}
+	}
+	/* Make this a compile time so that size of vBIOS doesn't become > 64KB */
+#if defined(CONFIG_PLB) || defined(CONFIG_TNC)
+	/* pwm backlight control needs graphics frequency. we currently implement
+	 * pwm backlight control for pouslbo only to limit the vbios lvds size. Each
+	 * chipset have a different method of getting this value and chipset has a
+	 * different multiplier. */
+	if (chipset == PCI_DEVICE_ID_VGA_PLB ||
+	    chipset == PCI_DEVICE_ID_VGA_TNC ||
+	    chipset == PCI_DEVICE_ID_VGA_TNC_A0 ||
+	    chipset == PCI_DEVICE_ID_VGA_LNC) {
+
+		/* For plb/tnc, graphics frequency is obtained by sending an opcode to
+		 * port 5 in the SCH Message Network. We call the read_regs with
+		 * PD_REG_BRIDGE_OPCODE specifically for this purpose only.
+		 *
+		 * The input for this read_reg is the opcode that register data that
+		 * we send into the Message control register*/
+		reg_list[1].reg = PD_REG_LIST_END;
+		ret = callback->read_regs(callback->callback_context,
+			reg_list, PD_REG_BRIDGE_OPCODE);
+		if(ret != PD_SUCCESS) {
+			return ret;
+		}
+
+		/*set the graphics frequency*/
+		pd_context->gfx_freq = (unsigned short) reg_list[0].value;
+	}
+#endif
+
+	pd_context->callback = callback;           /* Save callback context */
+	pd_context->chipset = chipset;            /* save the chipset ID   */
+	*context = (void *) pd_context;
+
+	PD_TRACE_EXIT;
+	return PD_SUCCESS;
+}                                                              /* lvds_open */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_init_device
+ *
+ * Description:
+ *    Initializes the LVDS device, using the device context from the parameter
+ *
+ * Parameters:
+ *    [INOUT] context:  device context
+ *
+ * Return:
+ *    PD_ERR_NULL_PTR:  if parameter is invalid
+ *    PD_SUCCESS:       if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int lvds_init_device (void *context)
+{                                                       /* lvds_init_device */
+	if (!context) {
+		return (PD_ERR_NULL_PTR);
+	}
+
+	/* Don't need to do much to initialize this device */
+	((lvds_context_t *)context)->init_done = 1;
+	lvds_driver.num_devices++;
+
+	return (PD_SUCCESS);
+}                                                       /* lvds_init_device */
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_close
+ *
+ * Description:
+ *    Releases resources allocated during lvds_open().  This function
+ *    essentially frees a device object.
+ *
+ * Parameters:
+ *    [INOUT] device_context:  device to be freed
+ *
+ * Return:
+ *    PD_SUCCESS: always returns this
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int lvds_close(void *device_context)
+{
+#ifndef CONFIG_MICRO
+
+	lvds_context_t *pd_context = (lvds_context_t *)device_context;
+
+	/* lvds_close */
+
+	PD_TRACE_ENTER;
+
+	/* Deallocate memory occupied by this device */
+	if (device_context) {
+		if ( NULL != pd_context->timing_table) {
+			pd_free(pd_context->timing_table);
+			pd_context->timing_table = NULL;
+		}
+
+		/* Free attribute list, if necessary */
+		/* FIXME -- The following test will never call pd_free(), because the
+		 * expression "!lvds_driver.num_devices" will yield 0 or 1, and that
+		 * will never be greater than 1.  This is a potentially small memory
+		 * leak, unless some other code frees it.
+		 */
+		if (!lvds_driver.num_devices > 1) {
+			pd_free(pd_context->attr_list);
+		}
+		/* This allocated statically no need to free it */
+		/* pd_free(device_context); */
+		lvds_driver.num_devices--;
+		pd_context->init_done = 0;
+	}
+
+	PD_TRACE_EXIT;
+#endif
+	return (PD_SUCCESS);
+}                                                             /* lvds_close */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_set_mode
+ *
+ * Description:
+ *    Sets LVDS to a new mode, specified by "mode".
+ *
+ * Parameters:
+ *    [INOUT] context:  device context
+ *    [IN]    mode:     information about the mode to switch to
+ *    [IN]    flags:    can contain the following value
+ *                PD_SET_MODE_FLAG_TEST:  only testing to see if mode is supported
+ *
+ * Return:
+ *    PD_ERR_NULL_PTR:     if invalid parameter detected
+ *    PD_ERR_MODE_NOTSUPP: if mode specified is not supported
+ *    PD_SUCCESS:          if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+int lvds_set_mode(void *context, pd_timing_t *mode, unsigned long flags)
+{
+	lvds_context_t *pd_context  = NULL;
+
+	PD_DEBUG("lvds_set_mode)\n");
+	PD_TRACE_ENTER;
+
+	pd_context = (lvds_context_t *)context;
+
+	/* Make sure these parameters are valid */
+	if (!pd_context || !mode) {
+		return (PD_ERR_NULL_PTR);
+	}
+	PD_DEBUG("lvds_set_mode: %ux%u", mode->width, mode->height);
+
+	/* Make sure specified mode is supported */
+	if ((pd_context->fp_width && (mode->width > pd_context->fp_width)) ||
+		(pd_context->fp_height && (mode->height > pd_context->fp_height))) {
+		return PD_ERR_MODE_NOTSUPP;
+	}
+
+	/* Do nothing if we are only want to know if a mode is supported */
+	if (flags & PD_SET_MODE_FLAG_TEST) {
+		return PD_SUCCESS;
+	}
+
+	pd_context->current_mode = mode;
+	pd_context->pipe = flags;
+	/* Enable panel fitting and return */
+	lvds_panel_fit(pd_context);
+
+	PD_TRACE_EXIT;
+
+	return PD_SUCCESS;
+}
+
+int lvds_post_set_mode(void *context, pd_timing_t *mode, unsigned long flags)
+{                                                          /* lvds_set_mode */
+	lvds_context_t *pd_context  = NULL;
+	unsigned long  port_control = 0;
+	unsigned long  preserve     = 0;
+	int            ret          = 0;
+
+	PD_TRACE_ENTER;
+	pd_context = (lvds_context_t *)context;
+
+	PD_DEBUG("lvds_post_set_mode)\n");
+	/* Make sure these parameters are valide */
+	if (!pd_context || !mode) {
+		return (PD_ERR_NULL_PTR);
+	}
+
+	/* Before enabling the LVDS port, make sure that display PLL for this pipe
+	 * is enabled and the port is power sequenced on using the panel power
+	 * sequencing logic. */
+
+	preserve = 0x3E007803;
+	port_control = preserve & lvds_read_reg(pd_context, 0x61180, PD_REG_MIO);
+	port_control |= BIT(31);          /* enable LVDS port */
+	if (flags & PD_SET_MODE_PIPE_B) {
+		port_control |= BIT(30);
+	}
+	port_control |= (BIT(9)|BIT(8));  /* power up */
+	port_control &= ~(BIT(21)|BIT(20)); /* Default sync polarites active high */
+
+	/* For gn4+, dither moved to port_control from panel_fit reg */
+	if (pd_context->gn4_plus) {
+		if (pd_context->panel_depth == 18) {
+			port_control |= BIT(25);
+		}
+
+		if (pd_context->dither != 0xFFFF) {
+			if (pd_context->dither) {
+				port_control |= BIT(25);
+			} else {
+				port_control &= ~BIT(25);
+			}
+		}
+	}
+
+	if((!pd_context->panel_fit) &&
+	   ( mode->width < pd_context->fp_width ||
+	     mode->height < pd_context->fp_height ) ){
+		port_control |= BIT(15); /* enable border in active for centering */
+	}
+
+	/*
+	 * Bit 24 for OpenLDI should be set to a 0 (1x18.0, 2x18.0, 1x24.0, 2x24.0).
+	 * From (B-Spec, Ref# 22316, section 1.15.3.8.3)
+	 *
+	 * Bit 24 for SPWG should be set to a 1 (1x24.1 or 2x24.1).
+	 *
+	 * This was verified by comparing the timing diagram for 1x24.0 in
+	 * OpenLDI spec (5.4.2.2 24-bit Single Pixel Mode, Unbalanced) with the
+	 * same diagram in the Display BSpec for Napa or Gen4.
+	 * A0 – A3 signals match the 1x24.0.
+	 *
+	 * From the OpenLDI spec (bit mappings are different):
+	 *
+	 * Table 5-2, Bit Number Mappings
+	 * 18 bpp bit# 24 bpp bit# OpenLDI bit#
+	 * 5           7           5
+	 * 4           6           4
+	 * 3           5           3
+	 * 2           4           2
+	 * 1           3           1
+	 * 0           2           0
+	 *             1           7
+	 *             0           6
+	 */
+
+	/* Attribute panel_type description:
+	 *  Attr ID    Attr Value        IntLVDS dataformat
+	 *  =======    ===============   ==================
+	 *    49       0  (SPWG)           1 (value of Bit 24)
+	 *    49       1  (OpenLDI)        0 (value of Bit 24)
+	 */
+	if (pd_context->panel_type == 0) {
+		port_control |= BIT(24); /* Dataformat 0 = SPWG, 1 = OpenLDI */
+	}
+
+	/* If the dual-channel is required, then power up second channel
+	 * ClkB and B0, B1, B2, (B3) */
+	if (pd_context->dual_channel) {
+		port_control |= (BIT(5)|BIT(4));  /* ClkB */
+		port_control |= (BIT(3)|BIT(2));  /* B0, B1, B2, (B3) */
+	}
+
+	/* Check for 18 or 24 bit panel */
+	if (pd_context->panel_depth == 24) {
+		/* If the panel is 24-bit (8-bpp), enable A3, (B3) pair. */
+		port_control |= (BIT(7)|BIT(6));
+	}
+
+	/* Set the sync polarities correctly if there is a native dtd */
+	if (pd_context->native_dtd) {
+		/* Set bit 20 for hsync active low */
+		if ((pd_context->native_dtd->mode_info_flags & PD_HSYNC_HIGH) == 0) {
+			port_control |= BIT(20);
+		}
+		/* Set bit 21 for vsync active low */
+		if ((pd_context->native_dtd->mode_info_flags & PD_VSYNC_HIGH) == 0) {
+			port_control |= BIT(21);
+		}
+	}
+
+    lvds_write_reg(pd_context, 0x61204, 0xABCD0000, 0xFFFFFFFF, PD_REG_MIO);
+
+	lvds_write_reg(pd_context, 0x61180, port_control, 0xFFFFFFFF, PD_REG_MIO);
+	ret = lvds_set_power(pd_context, PD_POWER_MODE_D0);
+	if (ret) {
+		PD_ERROR("PD set_power (D0) returned: 0x%x", ret);
+		return ret;
+	}
+
+    lvds_write_reg(pd_context, 0x61204, BIT(1), BIT(1), PD_REG_MIO);
+
+
+	PD_TRACE_EXIT;
+	/* Set the mode as per given timings */
+	return PD_SUCCESS;
+}                                                          /* lvds_set_mode */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_set_attrs
+ *
+ * Description:
+ *    Incorporate attributes in "list" into the device context.  This function
+ *    will override the initial attributes set by init_attrs.
+ *
+ * Parameters:
+ *    [INOUT] context:  device context
+ *    [IN] num:         not used, but must not be 0.
+ *    [IN] list:        list of attributes to incorporate into device context
+ *
+ * Return:
+ *    PD_ERR_NULL_PTR:          if one of the parameters is invalid
+ *    PD_ERR_ATTR_CANT_CHANGE:  attributes cannot be modified
+ *    PD_SUCCESS: if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+/* Tables required by Optimization Code. lvds_set_attrs() */
+typedef struct _opt_table_data {
+	unsigned long id;
+	unsigned short block;
+	unsigned short offset;
+} lvds_opt_table_data_t;
+static lvds_opt_table_data_t table_opt_data1[] = {
+
+	/*<--- id ---------->  <---block---> <------ offset -------------------> */
+	{PD_ATTR_ID_PANEL_DEPTH,     1, PD_OFFSETOF(lvds_context_t, panel_depth) },
+
+	{PD_ATTR_ID_2_CHANNEL_PANEL, 1, PD_OFFSETOF(lvds_context_t, dual_channel)},
+	{PD_ATTR_ID_LVDS_PANEL_TYPE, 1, PD_OFFSETOF(lvds_context_t, panel_type) },
+	{PD_ATTR_ID_PANEL_FIT,       1, PD_OFFSETOF(lvds_context_t, panel_fit)   },
+	{PD_ATTR_ID_DITHER,          1, PD_OFFSETOF(lvds_context_t, dither)      },
+	{PD_ATTR_ID_MAINTAIN_ASPECT_RATIO,1,PD_OFFSETOF(lvds_context_t,aspect_ratio)},
+	{PD_ATTR_ID_TEXT_TUNING,     1, PD_OFFSETOF(lvds_context_t, text_tune)},
+	{PD_ATTR_ID_PWM_INTENSITY,   1, PD_OFFSETOF(lvds_context_t, pwm_intensity)},
+	{PD_ATTR_ID_INVERTER_FREQ,   1, PD_OFFSETOF(lvds_context_t, inverter_freq)},
+	{PD_ATTR_ID_BLM_LEGACY_MODE, 1, PD_OFFSETOF(lvds_context_t, blm_legacy_mode)},
+	{LVDS_ATTR_ID_TC_LVDS_CLK,   1, PD_OFFSETOF(lvds_context_t, tc_110MHz_clk)},
+
+	/*<--- id ---------->  <---block---> <------ offset -------------------> */
+	{PD_ATTR_ID_FP_PWR_T1,       2,     0 }, /* 6 */
+	{PD_ATTR_ID_FP_PWR_T2,       2,     0 }, /* 7 */
+	{PD_ATTR_ID_FP_PWR_T3,       2,     0 }, /* 8 */
+	{PD_ATTR_ID_FP_PWR_T4,       2,     0 }, /* 9 */
+	{PD_ATTR_ID_FP_PWR_T5,       2,     0 }  /* 10 */
+};
+/* End of Tables required by Optimization Code. lvds_set_attrs() */
+
+int lvds_set_attrs (void *context, unsigned long num, pd_attr_t *list)
+{
+	lvds_context_t *pd_context = (lvds_context_t *) context;
+	pd_attr_t      *attr       = NULL;
+	unsigned short i           = 0;
+	unsigned short j           = 0;
+	int            ret         = PD_SUCCESS;
+	/* no of case IDs in the global table */
+	int num_case_ids = sizeof(table_opt_data1)/sizeof(lvds_opt_table_data_t);
+
+	/* basic parameter check */
+	if (!context || !num || !list) {
+		return PD_ERR_NULL_PTR;
+	}
+
+	PD_DEBUG("lvds_set_attrs()\n");
+	for (i = 0; i < num; i++, list++) {
+		/* do nothing if the attribute has not been changed */
+		if (!(list->flags & PD_ATTR_FLAG_VALUE_CHANGED)) {
+			continue;
+		}
+
+		/* attributes can't be changed after init has been completed */
+		if (list->flags & PD_ATTR_FLAG_USER_INVISIBLE &&
+			pd_context->init_done) {
+			return PD_ERR_ATTR_CANT_CHANGE;
+		}
+
+		/* Set the internal attributes' list.  Note that although get_attr() can
+		 * return NULL theortically, it will not do so here because all the
+		 * attribute IDs in this switch statement comes from lvds_attrs[],
+		 * a list that is automatically initialized into pd_context.  This is
+		 * why we are not checking for NULL after calling get_attr().
+		 */
+#if 0	/* ORIGINAL SWITCH STATEMENT */
+		switch (list->id) {
+			case PD_ATTR_ID_FP_PWR_T1:
+			case PD_ATTR_ID_FP_PWR_T2:
+			case PD_ATTR_ID_FP_PWR_T3:
+			case PD_ATTR_ID_FP_PWR_T4:
+			case PD_ATTR_ID_FP_PWR_T5:
+				/* current_value should not exceed the predefined max value */
+				attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+					list->id, 0);
+				attr->current_value = LVDS_MIN(
+						((pd_range_attr_t *)list)->current_value,
+						attr->_pad1);
+				break;
+
+			case PD_ATTR_ID_PANEL_DEPTH:
+				attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+					list->id, 0);
+				attr->current_value = list->current_value;
+				pd_context->panel_depth = (unsigned char) attr->current_value;
+				break;
+
+			case PD_ATTR_ID_2_CHANNEL_PANEL:
+				attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+					list->id, 0);
+				attr->current_value = ((pd_bool_attr_t *)list)->current_value;
+				pd_context->dual_channel = (attr->current_value?1:0);
+				break;
+
+			case PD_ATTR_ID_LVDS_PANEL_TYPE:
+				attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+					list->id, 0);
+				attr->current_value = ((pd_bool_attr_t *)list)->current_value;
+				pd_context->panel_type = (attr->current_value?1:0);
+				break;
+
+			case PD_ATTR_ID_PANEL_FIT:
+				attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+					list->id, 0);
+				attr->current_value = ((pd_bool_attr_t *)list)->current_value;
+				pd_context->panel_fit = (attr->current_value?1:0);
+				break;
+
+			default:
+				/* do nothing if we have an unknown ID */
+				break;
+		}
+#endif
+		/* OPTIMIZATION CODE BEGINS FOR THE ABOVE SWITCH
+		 *----------------------------------------------
+		 * Step 1: First identify the code common to all case blocks.
+		 *         This we call it "common code block" Since this is to be
+		 *         executed by all the case blocks.
+		 *
+		 * Step 2: Group the cases into blocks based on how we can combine them
+		 *
+		 *         Eg: case 0: ptr->x = 1; break; // similar code
+		 *        case 1: ptr->y = 1; break; // similar code
+		 *  ------Combined block ----
+		 *        case 0:
+		 *        case 1: PTR_OFFSET_TYPE(ptr, table[i].offset) = 1; break;
+		 *        This is an important step because we save code space by
+		 *        mapping many cases to smaller number of blocks. In the above
+		 *        we use index to get the right offset of the ptr.
+		 *
+		 * Step 3: Assign block IDs to each block. Put the case ID, block ID
+		 *         and other information such as offsets of ptr in a global
+		 *         table.
+		 *
+		 * Step 4: During run-time , search through the global table, find the
+		 *         matching case ID, and execute the common code. Next get the
+		 *         block ID and execute the block specific code. For the index,
+		 *         retrieve it from the table for the corresponding case ID.
+		 *
+		 * Step 5: If no matching case ID is found, error it out.
+		 *
+		 * Let's look at the optimization code for the above switch.
+		 * The code below searches for the list->id in a global table where
+		 * we store all the case values along with block numbers and other
+		 * information. After we find a valid id in the table , we execute the
+		 * common code for all cases first and then we retrieve the block id.
+		 * The block id is necesary to determine which block does the id belong
+		 * to. This is used to execute block specific code. Similar to switch
+		 * cases ONLY here we try to minimize the no of blocks.
+		 *
+		 * In this example , we store the offsets of field names of a ptr in the
+		 * global table.This is necessary to combine cases with "similar" but
+		 * not "same" codes.
+		 *
+		 * Eg: case 0: ptr->x = 1; break; // similar code
+		 *     case 1: ptr->y = 1; break; // similar code
+		 *  -- Combined block ----
+		 *    case 0:
+		 *    case 1: PTR_OFFSET_TYPE(ptr, table[i].offset) = 1; break;
+		 *
+		 * By reducing the number of blocks we save on Code space. After we
+		 * finish our work , we exit the for loop and check for invalid ID
+		 * passed by the upper layer. This is akin to default in the
+		 * switch block
+		 *
+		 * CAUTION: If there is any change in the switch above, this code
+		 * along with the tables have to be re-written and changed according
+		 * to the new behaviour of the switch. Examples include adding a new
+		 * case in the switch. The reason for all this mumbo-jumbo is to
+		 * reduce code size in VBIOS, where we are running out of code space.
+		 */
+		for(j = 0; j < num_case_ids; j++) {
+			/* Search for the attribute ID in the global table */
+			if(list->id == table_opt_data1[j].id) {
+				/* Run the common code for all the blocks */
+				attr = pd_get_attr(pd_context->attr_list, pd_context->num_attrs,
+					list->id, 0);
+				/* Once we get a valid ID, need to find out which block it
+				 *  belongs so we can execute block specific code.
+				 */
+				if(table_opt_data1[j].block == 1) { /* block 1 */
+					/* Got the block. Need the offset to the struct for that ID
+					* so we can store value at corresponding offset to get the
+					* desired behaviour for that ID.This is the code that makes
+					* the whole optimization work because we are combining the
+					* case IDs into a single block which saves code.
+					*/
+					attr->current_value = list->current_value;
+					PTR_OFFSET_USHORT(pd_context, table_opt_data1[j].offset) =
+					(unsigned short) attr->current_value;
+
+				} else { /* block 2. We only have two blocks. */
+					attr->current_value = LVDS_MIN(
+						list->current_value, ((pd_range_attr_t *)attr)->max);
+				}
+				break; /* We found a valid ID, so break inner for loop */
+			}
+		}
+	}
+	/* panel_type 0 (SPWG) isn't available for 18-bit depth */
+	PD_DEBUG("in LVDS_set_attributes()\n");
+	if (pd_context->panel_depth == 18) {
+		pd_context->panel_type = 1;
+	}
+	PD_DEBUG("IntLVDS: dual_channel=%u", pd_context->dual_channel);
+	PD_DEBUG("IntLVDS: panel_type=%u panel_fit=%u panel_dep=%u dither=%u",
+		pd_context->panel_type, pd_context->panel_fit,
+		pd_context->panel_depth, pd_context->dither);
+	PD_DEBUG("IntLVDS: keep_aspect_ratio=%u text_tune=%lu",
+		pd_context->aspect_ratio, pd_context->text_tune);
+	PD_DEBUG("IntLVDS: PWM Intensity=%u Inverter Freq=%u, BLM legacy mode =%u",
+		pd_context->pwm_intensity, pd_context->inverter_freq,
+		pd_context->blm_legacy_mode);
+	PD_DEBUG("IntLVDS: tc_110MHz_clk = %u", pd_context->tc_110MHz_clk);
+
+	if (pd_context->init_done) {
+		/* When emgd_driver_pre_init() pokes new attrs into this port driver,
+		 * pd_context->current_mode must be set before calling
+		 * lvds_panel_fit(), so set it to the first entry in the timing table:
+		 */
+		if (pd_context->current_mode == NULL) {
+			pd_context->current_mode = pd_context->timing_table;
+		}
+		lvds_panel_fit(pd_context);
+	}
+
+	return ret;
+} /* lvds_set_attrs */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_get_attrs
+ *
+ * Description:
+ *    Extracts the attribute list and the number of elements in the list
+ *    from the device context.
+ *
+ * Parameters:
+ *    [IN] context: device context to extract information from
+ *    [OUT] num:    number of elements in list
+ *    [OUT] list:   list of attributes from the device context
+ *
+ * Return:
+ *    PD_ERR_NULL_PTR: if one of the parameters is invalid
+ *    PD_SUCCESS:      if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+int lvds_get_attrs (void *context, unsigned long *num, pd_attr_t **list)
+{                                                         /* lvds_get_attrs */
+	/* basic parameter check */
+	if (!context || !num || !list) {
+		return PD_ERR_NULL_PTR;
+	}
+
+	PD_DEBUG("lvds_get_attrs()\n");
+	/* Nothing fancy, just extracting the elements from the list */
+	*list = ((lvds_context_t *)context)->attr_list;
+	*num  = ((lvds_context_t *)context)->num_attrs;
+
+	return PD_SUCCESS;
+}                                                         /* lvds_get_attrs */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_get_timing_list
+ *
+ * Description:
+ *
+ *
+ * Parameters:
+ *    [IN] context: device context to extract information from
+ *    [OUT] in_list:
+ *    [OUT] list:
+ *
+ * Return:
+ *    PD_ERR_NULL_PTR: if one of the parameters is invalid
+ *    PD_ERR_NOMEM:    if internal memory allocate failed
+ *    PD_SUCCESS:      if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+int lvds_get_timing_list (void *context, pd_timing_t *in_list,
+	pd_timing_t **list)
+{                                                   /* lvds_get_timing_list */
+	lvds_context_t *pd_context = (lvds_context_t *)context;
+	pd_dvo_info_t lvds_info = {0, 0, 1, 0, 0, 0, 0, 0};
+	pd_display_info_t lvds_display_info = {0, 0, 0, 0, NULL};
+	int ret;
+
+	PD_DEBUG("lvds_get_timing_list()\n");
+	lvds_get_dclk( pd_context, &lvds_info );
+
+	PD_DEBUG("chipset = 0x%x", pd_context->chipset);
+	lvds_display_info.panel_fit = (unsigned char) pd_context->panel_fit;
+	ret = pd_filter_timings(pd_context->callback->callback_context,
+		in_list, &pd_context->timing_table, &lvds_info, &lvds_display_info);
+
+	/* Helper function will return the below values */
+	pd_context->native_dtd = lvds_display_info.native_dtd;
+	pd_context->fp_width = lvds_display_info.width;
+	pd_context->fp_height = lvds_display_info.height;
+
+	*list = pd_context->timing_table;
+	return ret;
+}                                                   /* lvds_get_timing_list */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_set_power
+ *
+ * Description:
+ *  Sets LVDS to the specified power state
+ *
+ *  Conversion between IEGD timer values to LVDS port timer values
+ *
+ *  SEPG(?) IEGD    LVDS Port    Program bits     min     max
+ *  ----    ------- ------------ ---------------- ------ ---------
+ *  T1+T2   T1 ms   T1+T2 100us  0x61208 [28:16]  0 ms   819.2 ms
+ *  T5      T2 ms   T5    100us  0x61208 [12:00]  0 ms   819.2 ms
+ *  T6      T3 ms   Tx    100us  0x6120C [12:00]  0 ms   819.2 ms
+ *  T3      T4 ms   T3    100us  0x6120C [28:16]  0 ms   819.2 ms
+ *  T4      T5 ms   T4    100ms  0x61210 [04:00]  0 ms   3200  ms
+ *
+ *  Reg     = Value
+ *  ------    -------
+ *  0x61208 = [T1 T2]
+ *  0x6120C = [T4 T3]
+ *  0x61210 = [   T5]
+ *
+ * Parameters:
+ *    [IN] context: device context to extract information from
+ *    [OUT] in_list:
+ *    [OUT] list:
+ *
+ * Return:
+ *    PD_ERR_NULL_PTR:      if context is NULL
+ *    PD_ERR_INVALID_POWER: if "state" is invalid
+ *    PD_SUCCESS:           if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+/* Tables required by the optimization codes in lvds_set_power() */
+typedef struct {
+	unsigned char id1;
+	unsigned char id2;
+	unsigned char bit;
+	unsigned long reg;
+} opt_set_power_t;
+
+static opt_set_power_t table_set_power[] = {
+	/* id1                  id2                   bit    reg */
+	{ PD_ATTR_ID_FP_PWR_T1, PD_ATTR_ID_FP_PWR_T2, 1,     0x61208 },  /* D0 */
+	{ PD_ATTR_ID_FP_PWR_T4, PD_ATTR_ID_FP_PWR_T3, 0,     0x6120C },  /* Dx */
+};
+
+int lvds_set_power(void *context, unsigned long state)
+{                                                         /* lvds_set_power */
+	unsigned long  i           = 0;
+	lvds_context_t *pd_context = (lvds_context_t *)context;
+	pd_attr_t      *tattr      = NULL;  /* holds time delay b/ pwr transition */
+	unsigned long            delay = 0, delay1;
+
+	PD_DEBUG("state = %lu", state);
+
+	PD_DEBUG("lvds_set_power() to state = %lu\n",state);
+	/* Basic parameter check */
+	if (!context) {
+		PD_DEBUG("No context");
+		return PD_ERR_NULL_PTR;
+	}
+	PD_DEBUG("pd_context=0x%lx", (unsigned long)pd_context);
+
+	/* Check for invalid state */
+	if (state > PD_POWER_MODE_D3) {
+		PD_DEBUG("Invalid power state");
+		return PD_ERR_INVALID_POWER;
+	}
+
+	/* Get the index into above table */
+	if (state == PD_POWER_MODE_D0) {
+		i = 0;
+	} else {
+		i = 1;
+	}
+
+	lvds_write_reg(pd_context, 0x61204, 0xABCD0000, 0xFFFFFFFF, PD_REG_MIO);
+
+	/* Program panel power up/down delays: Either T1/T2 or T3/T4*/
+	tattr = pd_get_attr(pd_context->attr_list,
+		pd_context->num_attrs, table_set_power[i].id1, 0);
+	/* Convert ms to 100us */
+	delay1 = tattr->current_value;
+	delay = (tattr->current_value * 10) << 16;
+	tattr = pd_get_attr(pd_context->attr_list,
+		pd_context->num_attrs, table_set_power[i].id2, 0);
+	delay1 += tattr->current_value;
+	delay |= tattr->current_value * 10;
+
+	lvds_write_reg(pd_context, table_set_power[i].reg, delay, 0x1FFF1FFF, PD_REG_MIO);
+
+	/* Program power cycle delay: convert ms to 100ms */
+	delay = pd_get_attr(pd_context->attr_list,
+		pd_context->num_attrs, PD_ATTR_ID_FP_PWR_T5, 0)->current_value;
+	delay1 += delay;
+	/* TODO: Write reference divider [31:8] */
+	delay = ((delay/100+1) & 0xFF) | ((pd_context->gfx_freq*100/2-1)<<8);
+	lvds_write_reg(pd_context, 0x61210, delay, 0xFFFFFFFF, PD_REG_MIO);
+
+	/* Power state target */
+	lvds_write_reg(pd_context, 0x61204, table_set_power[i].bit, BIT(0), PD_REG_MIO);
+
+	/* Power down on reset available on crestline onwards */
+	lvds_write_reg(pd_context, 0x61204, BIT(1), BIT(1), PD_REG_MIO);
+
+/* Make this a compile time so that size of vBIOS doesn't become > 64KB */
+#if defined(CONFIG_PLB) || defined(CONFIG_TNC)
+	/* PWM is a method of controlling the backlight intensity.
+	 * It is not method to turn on baclkight.
+	 * We still need the PD method to turn on the backlight.
+	 *
+	 * This feature is for Pouslbo Only. We check that the user has set the
+	 * inverter frequency. Default intensity, if not set, is 100%
+	 *
+	 * Due to the high amount of calculation, we want to only set this register
+	 * if it has not been ser previously. The register could be
+	 * "brought forward" from VBIOS.
+	 */
+	if(pd_context->inverter_freq != 0xFFFF &&  /* Overwritten by set_attr */
+		(pd_context->chipset == PCI_DEVICE_ID_VGA_PLB ||
+		 pd_context->chipset == PCI_DEVICE_ID_VGA_TNC ||
+		 pd_context->chipset == PCI_DEVICE_ID_VGA_TNC_A0 ||
+		 pd_context->chipset == PCI_DEVICE_ID_VGA_LNC) &&
+		 !pd_context->pwm_done) {
+		unsigned long reg_value = 0;
+		unsigned long percentage = 0;
+		unsigned long calculation = 0;
+		unsigned long blc_pwm_ctl2 = 0;
+
+		/* We first need to get the graphics frequency, which will be used to
+		 * calculate Backlight Modulation Frequency[BMF]. BMF will be used to
+		 * fill up the 15 MSB in the 0x61254 register
+		 *
+		 * The calculation for the Modulation Frequency field in the
+		 * BLC_PWM_CTL Register is:
+		 *
+         *     Reference Clock Freq               1
+         *     -----------------------   x    ------------------
+         *            Divider                   PWM Freq in Hz
+		 *
+		 */
+#if 0
+		/* GMA accurate calculation that requires "calculation" to be an
+		 * unsigned long long typedef */
+		calculation = pd_context->gfx_freq * PWM_FREQ_CALC_CONSTANT_2;
+		calculation = calculation / 0x20; /*pouslbo specific divider*/
+		calculation = calculation * PWM_FREQ_CALC_CONSTANT_1;
+		calculation = calculation / pd_context->inverter_freq;
+		calculation = calculation / PWM_FREQ_CALC_CONSTANT_1;
+#endif
+		/* Some system bios cannot take 64 bit data type. Using a more
+		 * simplified calculation that is not too accurate if the inputs
+		 * are not round numbers */
+		calculation = pd_context->inverter_freq * 0x20; /* plb/tnc divider */
+		calculation = (pd_context->gfx_freq * PWM_FREQ_CALC_CONSTANT_2) /
+			calculation;
+
+		/* Writing the register: 15 MSB is the max lvds clock / 32.
+		* Bit 16 can either be legacy or non legacy depending upon Attr #72. */
+		if (pd_context->gn4_plus) {
+			blc_pwm_ctl2 = (1L << 31) |
+				(pd_context->blm_legacy_mode << 30) |
+				((pd_context->pipe == PD_SET_MODE_PIPE_B)?1L:0L << 29);
+			lvds_write_reg(pd_context, 0x61250, blc_pwm_ctl2, 0xFFFFFFFF, PD_REG_MIO);
+			reg_value = (calculation & 0xFFFF)<<16;
+		} else {
+			reg_value = ((calculation & 0xFFFE) |
+				pd_context->blm_legacy_mode)<<16;
+		}
+
+		/* The 16 LSB is a value that the user sets in configuration.
+		 * user sets the value in percentage.
+		 * We convert it into the clock speed */
+		percentage = ( pd_context->pwm_intensity * (unsigned long)calculation);
+		reg_value |= (unsigned long)( percentage / (int)100 ) & 0xFFFE;
+		lvds_write_reg(pd_context, 0x61254, reg_value, 0xFFFFFFFF, PD_REG_MIO);
+
+		/* set the flag so that we only do this function once */
+		pd_context->pwm_done = 1;
+	}
+#endif
+
+	if (state != PD_POWER_MODE_D0) {
+		/* Wait until the current power up/down sequence is complete */
+		i = 0;
+		while(lvds_read_reg(pd_context, 0x61200, PD_REG_MIO) & 0x80000000L) {
+			i++;
+			if(i > 0x100000L) {
+				break;
+			}
+		}
+		lvds_write_reg(pd_context, 0x61180, 0, BIT(31), PD_REG_MIO);
+	}
+
+#ifdef CONFIG_TNC
+#if 0
+
+/*-----------------------------------------------------------------------------
+ * LPC Register Offsets. Used for LVDS BKLT control. Registers are part
+ * Atom E6xx [D31:F0]
+ ----------------------------------------------------------------------------*/
+#define RGEN    0x20
+#define RGIO    0x24
+#define RGLVL   0x28
+#define TNC_LVDS_VDDEN	 BIT(0)
+#define TNC_LVDS_BKLTEN  BIT(1)
+#define TNC_LVDS_BKLTCTL BIT(2)
+
+	if (pd_context->chipset == PCI_DEVICE_ID_VGA_TNC ||
+		pd_context->chipset == PCI_DEVICE_ID_VGA_TNC_A0 ||
+		pd_context->chipset == PCI_DEVICE_ID_VGA_LNC) {
+		unsigned long value;
+
+		/* Enable backlight for LVDS: based on observed si behavior:
+		 * Subject to change based on si DE feedback */
+		if (state == PD_POWER_MODE_D0) {
+			value = TNC_LVDS_BKLTCTL|TNC_LVDS_BKLTEN|TNC_LVDS_BKLTCTL;
+		} else {
+			value = 0;
+		}
+		lvds_write_reg(pd_context, RGEN, value,
+			TNC_LVDS_BKLTCTL|TNC_LVDS_BKLTEN|TNC_LVDS_BKLTCTL, PD_REG_LPC);
+		lvds_write_reg(pd_context, RGIO, value,
+			TNC_LVDS_BKLTCTL|TNC_LVDS_BKLTEN|TNC_LVDS_BKLTCTL, PD_REG_LPC);
+	}
+#endif
+#endif
+
+	/* update power state */
+	pd_context->power_state = state;
+	return PD_SUCCESS;
+}                                                         /* lvds_set_power */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_get_power
+ *
+ * Description:
+ *   Returns the current LVDS power state back to the caller.
+ *
+ * Parameters:
+ *    [IN] context: device context to extract information from
+ *    [OUT] state:  current power state
+ *
+ * Return:
+ *    PD_ERR_NULL_PTR:      if one of the parameters is invalid
+ *    PD_SUCCESS:           if successful
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int lvds_get_power (void *context, unsigned long *state)
+{                                                         /* lvds_get_power */
+	if ((NULL == context) || (NULL == state)) {
+		return PD_ERR_NULL_PTR;
+	}
+	PD_DEBUG("lvds_get_power()\n");
+	/* The caller should be able to do this himself, but whatever */
+	*state = ((lvds_context_t *) context)->power_state;
+	return PD_SUCCESS;
+}                                                         /* lvds_get_power */
+
+int lvds_save(void *context, void **state, unsigned long flags)
+{
+	*state = NULL;
+	return PD_SUCCESS;
+}
+
+int lvds_restore(void *context, void *state, unsigned long flags)
+{
+	int ret = PD_SUCCESS;
+	return ret;
+}
+
+/*----------------------------------------------------------------------
+ * Function: lvds_get_port_status()
+ *
+ * Description:  It is called to get the information about the display
+ *
+ * Parameters:  context - Port driver's context
+ *				port_status - Returns the display type and connection state
+ *
+ * Return:      PD_SUCCESS(0)  success
+ *              PD_ERR_XXXXXX  otherwise
+ *----------------------------------------------------------------------*/
+int lvds_get_port_status(void *context, pd_port_status_t *port_status)
+{
+	/* Display connection cannot be determined */
+	port_status->display_type = PD_DISPLAY_LVDS_INT;
+	port_status->connected    = PD_DISP_STATUS_UNKNOWN;
+	return PD_SUCCESS;
+}
+
+static unsigned long lvds_read_reg(lvds_context_t *pd_context,unsigned long reg,
+	unsigned long reg_type)
+{
+	pd_reg_t list[2];
+	int ret;
+
+	list[0].reg = reg;
+	list[0].value = 0;
+	list[1].reg = PD_REG_LIST_END;
+	ret = pd_context->callback->read_regs(
+		pd_context->callback->callback_context, list, reg_type);
+	if (ret) {
+		PD_ERROR("LVDS read regs: Failed.");
+	}
+	return list[0].value;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_write_reg
+ *
+ * Description:
+ *    Writes bits in "value" into a register.  Bits written are dictated by
+ *    the "change_bits" mask.
+ *
+ * Parameters:
+ *    [IN] pd_context:  device context, dispatcher to the actual write_reg
+ *                      function
+ *    [IN] reg:  register to write value to
+ *    [IN] value:  value to change the register to
+ *    [IN] change_bits:  bit mask, the bits set to "1" will be modified by
+ *                       the corresponding bits in "value"
+ *
+ * Return:
+ *    None
+ *
+ *----------------------------------------------------------------------------
+ */
+static void lvds_write_reg(lvds_context_t *pd_context, unsigned long reg,
+		unsigned long value,
+		unsigned long change_bits,
+		unsigned long reg_type)
+{                                                         /* lvds_write_reg */
+	pd_reg_t list[2];
+	int ret;
+
+	PD_DEBUG("ENTER");
+
+	list[0].reg = reg;
+	list[0].value = (lvds_read_reg(pd_context, reg, PD_REG_MIO) & ~change_bits) | value;
+	list[1].reg = PD_REG_LIST_END;
+	ret = pd_context->callback->write_regs(
+		pd_context->callback->callback_context, list, reg_type);
+	if (ret) {
+		PD_ERROR("LVDS write regs: Failed.");
+	}
+	PD_DEBUG("EXIT");
+	return;
+}                                                         /* lvds_write_reg */
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_panel_fit
+ *
+ * Description:
+ *    Enables panel fitting
+ *
+ * Parameters:
+ *    [IN] pd_context:  device context
+ *
+ * Return:
+ *    None
+ *
+ *----------------------------------------------------------------------------
+ */
+static void lvds_panel_fit(lvds_context_t *pd_context)
+{
+	/* enable auto vertical ratio */
+	/* enable auto horizantal ratio */
+	/* no dither */
+	unsigned long panel_fit_reg = 0x00000220;
+	PD_DEBUG("lvds_panel_fit() \n");
+
+	PD_TRACE_ENTER;
+
+	if (pd_context->current_mode->width != pd_context->fp_width ||
+		pd_context->current_mode->height != pd_context->fp_height) {
+		/* Enable panel fitting */
+		/* vertical interpolation = bilinear */
+		/* horizontal interpolation = bilinear */
+		panel_fit_reg |= 0x80000440;
+	}
+	/* Enable dither based on default/user-set value:
+	 *   By default
+	 *        dither = 1 for 18-bit panels
+	 *               = 0 for 24-bit panels.
+	 *   But this behavior can be changed by setting the DITHER attribute.
+	 *        When user sets the attribute, dither will be updated
+	 *        as part of attribute processing in set attributes. */
+	/* For gn4 based chipsets dither is controlled in port_control register */
+	if (!pd_context->gn4_plus) {
+		/* Default behavior */
+		if (pd_context->panel_depth == 18) {
+			panel_fit_reg |= BIT(3);
+		}
+
+		/* Overwritten by set attribute */
+		if (pd_context->dither != 0xFFFF) {
+			if (pd_context->dither) {
+				panel_fit_reg |= BIT(3);
+			} else {
+				panel_fit_reg &= ~BIT(3);
+			}
+		}
+	}
+
+	if (pd_context->gn4_plus) {
+		unsigned long src_ratio, dest_ratio;
+		panel_fit_reg = 0;
+		if (pd_context->native_dtd &&
+			(pd_context->current_mode->width != pd_context->native_dtd->width ||
+			pd_context->current_mode->height !=
+				pd_context->native_dtd->height)) {
+			/* Enable panel fitter */
+			panel_fit_reg = 0x80000000;
+
+			/* Select the pipe */
+			if (pd_context->pipe & PD_SET_MODE_PIPE_B) {
+				panel_fit_reg |= BIT(29);   /* bits[30:29] = 01 for pipe B */
+			}
+
+			/* Scaling mode:
+			 *    Default - Auto scaling src_ratio == dest_ratio
+			 *    Piller box scaling - src_ratio < dest_ratio
+			 *    Letter box scaling - src_ratio > dest_ratio */
+
+			/* To make this work correctly, port driver shall know the
+			 * size of the framebuffer, not the src mode. Most of the
+			 * times the src mode is fb, but not all the cases.
+			 * User has an attribute to change
+			 *    1. Between Pillerbox and auto, and vice versa
+			 *                and
+			 *    2. Between Letterbox and auto, and vice versa.
+			 */
+			if (pd_context->aspect_ratio) {
+				src_ratio = (pd_context->current_mode->width << 10)/
+					(pd_context->current_mode->height);
+				dest_ratio = (pd_context->native_dtd->width << 10)/
+					(pd_context->native_dtd->height);
+
+				if (dest_ratio > src_ratio) {
+					/* Pillarbox scaling */
+					panel_fit_reg |= BIT(27);
+				} else if (dest_ratio < src_ratio) {
+					/* Letterbox scaling */
+					panel_fit_reg |= BIT(27) | BIT(26);
+				}
+			}
+
+			/* Filter coefficient select: pd_context->text_tune = 0,1,2 */
+			panel_fit_reg |= (pd_context->text_tune << 24);
+		}
+	}
+
+	lvds_write_reg(pd_context, 0x61230, panel_fit_reg, 0xFFFFFFFF, PD_REG_MIO);
+	PD_DEBUG("panel_fit_reg 0x61230 = 0x%lx", panel_fit_reg);
+}
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: lvds_get_dclk
+ *
+ * Description:
+ *    Gets the Dclk for LVDS
+ *
+ * Parameters:
+ *    [IN] pd_context:  device context
+ *	  [OUT]lvds_info:   Structure that contains the min and max dclk
+ *
+ * Return:
+ *    None
+ *
+ *----------------------------------------------------------------------------
+ */
+static void lvds_get_dclk(lvds_context_t *pd_context, pd_dvo_info_t *lvds_info )
+{
+	PD_DEBUG("lvds_get_dclk()\n");
+	/* Get the min and max dclks for lvds */
+	if (pd_context->dual_channel) {
+		lvds_info->min_dclk = LVDS_MIN_DCLK * 2 ;
+		lvds_info->max_dclk = LVDS_MAX_DCLK * 2;
+	} else {
+		lvds_info->min_dclk = LVDS_MIN_DCLK;
+		lvds_info->max_dclk = LVDS_MAX_DCLK;
+	}
+/* This #define is the result of code size reduction effort. */
+#ifdef CONFIG_CTG
+	/* Set dclk for GM965 */
+	if(pd_context->chipset==PCI_DEVICE_ID_VGA_CTG){
+		/* Set dclk for GM965/CTG */
+		if (pd_context->dual_channel) {
+			lvds_info->min_dclk = LVDS_GM965_DUAL_MIN_DCLK ;
+			lvds_info->max_dclk = LVDS_GM965_DUAL_MAX_DCLK;
+		} else {
+			lvds_info->min_dclk = LVDS_GM965_SINGLE_MIN_DCLK;
+			lvds_info->max_dclk = LVDS_GM965_SINGLE_MAX_DCLK;
+		}
+	}
+#else
+
+	/* Set dclk for 915GM */
+	if(pd_context->chipset==PCI_DEVICE_ID_VGA_915AL){
+		if (pd_context->dual_channel) {
+			lvds_info->min_dclk = LVDS_915GM_DUAL_MIN_DCLK ;
+			lvds_info->max_dclk = LVDS_915GM_DUAL_MAX_DCLK;
+		} else {
+			lvds_info->min_dclk = LVDS_915GM_SINGLE_MIN_DCLK;
+			lvds_info->max_dclk = LVDS_915GM_SINGLE_MAX_DCLK;
+		}
+	} else if(pd_context->chipset==PCI_DEVICE_ID_VGA_945GM ||
+				pd_context->chipset==PCI_DEVICE_ID_VGA_945GME){
+		/* Set dclk for 945GM */
+		if (pd_context->dual_channel) {
+			lvds_info->min_dclk = LVDS_945GM_DUAL_MIN_DCLK ;
+			lvds_info->max_dclk = LVDS_945GM_DUAL_MAX_DCLK;
+		} else {
+			lvds_info->min_dclk = LVDS_945GM_SINGLE_MIN_DCLK;
+			lvds_info->max_dclk = LVDS_945GM_SINGLE_MAX_DCLK;
+		}
+	} else if(pd_context->chipset==PCI_DEVICE_ID_VGA_GM965 ||
+				pd_context->chipset==PCI_DEVICE_ID_VGA_GME965){
+		/* Set dclk for GM965 */
+		if (pd_context->dual_channel) {
+			lvds_info->min_dclk = LVDS_GM965_DUAL_MIN_DCLK ;
+			lvds_info->max_dclk = LVDS_GM965_DUAL_MAX_DCLK;
+		} else {
+			lvds_info->min_dclk = LVDS_GM965_SINGLE_MIN_DCLK;
+			lvds_info->max_dclk = LVDS_GM965_SINGLE_MAX_DCLK;
+		}
+	}
+#endif
+
+#ifdef CONFIG_TNC
+	/* Get the min and max dclks for Atom E6xx lvds */
+	if ((pd_context->chipset == PCI_DEVICE_ID_VGA_TNC) ||
+	    (pd_context->chipset == PCI_DEVICE_ID_VGA_TNC_A0) ||
+	    (pd_context->chipset == PCI_DEVICE_ID_VGA_LNC)) {
+		lvds_info->min_dclk = LVDS_TNC_SINGLE_MIN_DCLK;
+		/* Experimental feature to raise TC LVDS clk to 110MHz. */
+		if (pd_context->tc_110MHz_clk) {
+			lvds_info->max_dclk = 110000L;
+		} else {
+			lvds_info->max_dclk = LVDS_TNC_SINGLE_MAX_DCLK;
+		}
+	}
+#endif
+}
diff --git a/drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.h b/drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.h
new file mode 100644
index 0000000..dd9cc87
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/lvds/lvds.h
@@ -0,0 +1,164 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: lvds.h
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is header file for Internal LVDS PORT DRIVER.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PD_LVDS_H
+#define _PD_LVDS_H
+
+#include <pd.h>
+#include <pci.h>
+
+/* Values received from DPG hardware engineer. These are for single channel.  */
+
+#ifndef PCI_DEVICE_ID_VGA_855
+#define PCI_DEVICE_ID_VGA_855      0x3582
+#endif
+#ifndef PCI_DEVICE_ID_VGA_915AL
+#define PCI_DEVICE_ID_VGA_915AL    0x2592
+#endif
+#ifndef PCI_DEVICE_ID_VGA_945GM
+#define PCI_DEVICE_ID_VGA_945GM    0x27A2
+#endif
+#ifndef PCI_DEVICE_ID_VGA_945GME
+#define PCI_DEVICE_ID_VGA_945GME   0x27AE
+#endif
+#ifndef PCI_DEVICE_ID_VGA_GM965
+#define PCI_DEVICE_ID_VGA_GM965    0x2A02
+#endif
+#ifndef PCI_DEVICE_ID_VGA_GME965
+#define PCI_DEVICE_ID_VGA_GME965   0x2A12
+#endif
+#ifndef PCI_DEVICE_ID_VGA_CTG
+#define PCI_DEVICE_ID_VGA_CTG      0x2A42
+#endif
+#ifndef PCI_DEVICE_ID_VGA_PLB
+#define PCI_DEVICE_ID_VGA_PLB      0x8108
+#endif
+#ifndef PCI_DEVICE_ID_VGA_TNC
+#define PCI_DEVICE_ID_VGA_TNC      0x4108
+#endif
+#ifndef PCI_DEVICE_ID_VGA_TNC_A0
+#define PCI_DEVICE_ID_VGA_TNC_A0   0x4100
+#endif
+#ifndef PCI_DEVICE_ID_VGA_LNC
+#define PCI_DEVICE_ID_VGA_LNC      0x4102
+#endif
+
+
+#define LVDS_MIN_DCLK 12000L    /* in KHz */
+#define LVDS_MAX_DCLK 112000L   /* in KHz */
+/* definition for 915GM */
+#define LVDS_915GM_SINGLE_MIN_DCLK   20000L
+#define LVDS_915GM_SINGLE_MAX_DCLK  112000L
+#define LVDS_915GM_DUAL_MIN_DCLK     25000L
+#define LVDS_915GM_DUAL_MAX_DCLK    224000L
+
+/* definition for 945GM */
+#define LVDS_945GM_SINGLE_MIN_DCLK   25000L
+#define LVDS_945GM_SINGLE_MAX_DCLK  112000L
+#define LVDS_945GM_DUAL_MIN_DCLK     25000L
+#define LVDS_945GM_DUAL_MAX_DCLK    224000L
+
+/* definition for GM965 */
+#define LVDS_GM965_SINGLE_MIN_DCLK   25000L
+#define LVDS_GM965_SINGLE_MAX_DCLK  112000L
+#define LVDS_GM965_DUAL_MIN_DCLK     25000L
+#define LVDS_GM965_DUAL_MAX_DCLK    224000L
+
+/* definition for Atom E6xx */
+#define LVDS_TNC_SINGLE_MIN_DCLK     19750L
+#define LVDS_TNC_SINGLE_MAX_DCLK     79500L
+
+#define LVDS_MIN(a, b)       ((a)<(b)?(a):(b))
+
+/* Local attributes
+ * BIT15 of attribute Id specifies that it is a local attribute */
+#define LVDS_ATTR_ID_DATA_FORMAT   (BIT(15)|1)
+#define LVDS_ATTR_ID_TC_LVDS_CLK   (BIT(15)|2)
+
+/* Default values */
+#define LVDS_DEF_PANEL_DEPTH    18      /* Default panel depth */
+#define LVDS_DEF_DITHER          1      /* default=1 as default panel depth=18*/
+#define LVDS_DEF_SCALE_ON        1      /* Default scaling is on */
+#define LVDS_DEF_PANEL_FIT       1      /* Default panel fit in on */
+
+typedef struct _lvds_context {
+	unsigned short fp_width;
+	unsigned short fp_height;
+	unsigned short dual_channel;
+	unsigned short panel_type;
+	unsigned short panel_fit;
+	unsigned short panel_depth;
+	unsigned short dither;
+	unsigned short aspect_ratio;
+	unsigned long  text_tune;
+	unsigned long  pwm_intensity;
+	unsigned long  inverter_freq;
+	unsigned long  blm_legacy_mode;
+
+	unsigned long power_state;
+	unsigned short chipset;
+	unsigned char init_done;
+	unsigned char num_attrs;
+	unsigned long pipe;
+	unsigned short gfx_freq;
+	unsigned char gn4_plus;
+	unsigned char pwm_done;
+	unsigned char tc_110MHz_clk;
+
+	pd_callback_t *callback;
+	pd_timing_t   *timing_table;
+	pd_attr_t     *attr_list;
+	pd_timing_t   *native_dtd;
+	pd_timing_t   *current_mode;
+} lvds_context_t;
+
+extern int PD_MODULE_INIT(lvds_init, (void *handle));
+extern int PD_MODULE_EXIT(lvds_exit, (void));
+extern unsigned long lvds_validate(unsigned long cookie);
+extern int lvds_open(pd_callback_t *callback, void **context);
+extern int lvds_init_device(void *context);
+extern int lvds_close(void *context);
+extern int lvds_set_mode(void *context, pd_timing_t *mode,
+			unsigned long flags);
+extern int lvds_post_set_mode(void *context, pd_timing_t *mode,
+			unsigned long flags);
+extern int lvds_set_attrs(void *context, unsigned long num, pd_attr_t *list);
+extern int lvds_get_attrs(void *context, unsigned long*num, pd_attr_t **list);
+extern int lvds_get_timing_list(void *context, pd_timing_t *in_list,
+			pd_timing_t **list);
+extern int lvds_set_power(void *context, unsigned long state);
+extern int lvds_get_power(void *context, unsigned long *state);
+extern int lvds_save(void *context, void **state, unsigned long flags);
+extern int lvds_restore(void *context, void *state, unsigned long flags);
+extern int lvds_get_port_status(void *context, pd_port_status_t *port_status);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo.def b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo.def
new file mode 100644
index 0000000..f271b16
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo.def
@@ -0,0 +1,25 @@
+# Copyright (c) 2002-2011, Intel Corporation.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+LIBRARY sdvo
+
+EXPORTS
+    get_version
+    dpd_init
diff --git a/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.c b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.c
new file mode 100644
index 0000000..6d2d3c8
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.c
@@ -0,0 +1,1484 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sdvo_attr.c
+ * $Revision: 1.16 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Functions to
+ *  Create Display Attribute table
+ *  Query and Alter attributes
+ *-----------------------------------------------------------------------------
+ */
+
+#include "sdvo_port.h"
+
+/* .......................................................................... */
+#ifndef CONFIG_MICRO
+#define MAKE_NAME(x)    x
+#else
+#define MAKE_NAME(x)    NULL
+#endif
+
+
+/* .......................................................................... */
+/*    Panel Power Sequencing Parameters */
+static pd_range_attr_t g_panel_power_attr[] =
+{
+		/*       ID                      Type                 Name */
+		/*       Flags   Default Value   Current Value   Min  Max Step */
+	PD_MAKE_ATTR(PD_ATTR_ID_FP_PWR_T1,   PD_ATTR_TYPE_RANGE, "FP Power T1",
+				PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 1),
+
+	PD_MAKE_ATTR(PD_ATTR_ID_FP_PWR_T2,   PD_ATTR_TYPE_RANGE, "FP Power T2",
+				PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 1),
+
+	PD_MAKE_ATTR(PD_ATTR_ID_FP_PWR_T3,   PD_ATTR_TYPE_RANGE, "FP Power T3",
+				PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 1),
+
+	PD_MAKE_ATTR(PD_ATTR_ID_FP_PWR_T4,   PD_ATTR_TYPE_RANGE, "FP Power T4",
+				PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 1),
+
+	PD_MAKE_ATTR(PD_ATTR_ID_FP_PWR_T5,   PD_ATTR_TYPE_RANGE, "FP Power T5",
+				PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 1),
+};
+
+static pd_range_attr_t g_fp_attr[] = {
+	/* Do not change the order of entries */
+		/*       ID                     Type                Name */
+		/* Flags  Default Value   Current Value   Min  Max Step */
+	PD_MAKE_ATTR(PD_ATTR_ID_DISPLAY,    PD_ATTR_TYPE_RANGE, "Display Type",
+		 PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0x4000, 1),
+
+	PD_MAKE_ATTR(PD_ATTR_ID_PANEL_FIT,  PD_ATTR_TYPE_BOOL,  "PanelFit",
+		 PD_ATTR_FLAG_USER_INVISIBLE, 0, 0, 0, 0, 0),
+
+	PD_MAKE_ATTR(PD_ATTR_ID_TEXT_TUNING,PD_ATTR_TYPE_RANGE, "Text Enhancement",
+		0,            0,              0,           0,  4,  1),
+
+	PD_MAKE_ATTR(PD_ATTR_ID_RB_SWAP_MODE, PD_ATTR_TYPE_BOOL,"RB Swap", 0, 0x00,	0x00, 0, 0, 0),
+};
+#ifndef CONFIG_MICRO
+static sdvo_tv_optimal_settings_t g_sdtv_op_settings[] =
+/*	chron_tv_code [7:0]
+ *		bits[7:2] = tv_format
+ *			480i = 0x00 ; 576i = 0x24 ; other TV line formats = 0xFF => for higher
+ *       resolution, YPbPr is the implied connector
+ *		bits [1:0] = output type
+ *			CVBS = 0x00, SVIDEO = 0x01, YPbPr = 0x02, SCART = 0x03
+ *	chron_tv_code,		hue,		saturation,		brightness,		contrast */
+{
+	/* SDTV [480i, 576i] - analog format w/
+	 * CVBS / SVIDEO / SCART / YPbPr connector */
+	/* NTSC_M Composite */
+	{0x00,	0x3F,		0x35,			0x81,			0x2F},
+	/* NTSC_M Svideo */
+	{0x01,	0x3D,		0x30,			0x81,			0x2F},
+	/* PAL_B/D/G/H/I/K/L Composite */
+	{0x24,	0x41,		0x38,			0x74,			0x3B},
+	/* PAL_B/D/G/H/I/K/L Svideo */
+	{0x25,	0x3F,		0x30,			0x74,			0x3B},
+	/* SECAM xxx- */
+
+	/* EDTV [ 480p, 576p] + HDTV [720p, 1080i/p] ) -
+	 * analog format w/ YPbPr connector */
+	{0xFF,	0x40,		0x45,			0x80,			0x2C},
+};
+#endif
+/* .......................................................................... */
+static sdvo_range_attr_data_t g_range_data[] =
+/*  ID                          Name                              Bytes*/
+/*  opcode_max                  opcode_get              opcode_set */
+{
+ {PD_ATTR_ID_BRIGHTNESS,        MAKE_NAME("Brightness"),            2,
+  GET_MAX_BRIGHTNESS,           GET_BRIGHTNESS,         SET_BRIGHTNESS},
+
+ {PD_ATTR_ID_PANEL_DEPTH,       MAKE_NAME("Panel Depth"),           1,
+  GET_LVDS_PANEL_INFORMATION,   GET_LVDS_PANEL_INFORMATION,
+													SET_LVDS_PANEL_INFORMATION},
+#ifndef CONFIG_MICRO
+ {PD_ATTR_ID_FP_BACKLIGHT_EN,   MAKE_NAME("Backlight Level"),       1,
+  GET_MAX_BACKLIGHT_LEVEL,      GET_BACKLIGHT_LEVEL,    SET_BACKLIGHT_LEVEL},
+
+ {PD_ATTR_ID_FLICKER,			MAKE_NAME("Flicker Filter"),		2,
+  GET_MAX_FLICKER_FILTER,		GET_FLICKER_FILTER, 	SET_FLICKER_FILTER},
+
+ {PD_ATTR_ID_2D_FLICKER,		MAKE_NAME("2D Flicker Filter"),		2,
+  GET_MAX_2D_FLICKER_FILTER,	GET_2D_FLICKER_FILTER,	SET_2D_FLICKER_FILTER},
+
+ {PD_ATTR_ID_SATURATION,		MAKE_NAME("Saturation"),				2,
+  GET_MAX_SATURATION,			GET_SATURATION, 		SET_SATURATION},
+
+ {PD_ATTR_ID_HUE,				MAKE_NAME("Hue"),					2,
+  GET_MAX_HUE,					GET_HUE,				SET_HUE},
+
+ {PD_ATTR_ID_CONTRAST,			MAKE_NAME("Contrast"), 			2,
+  GET_MAX_CONTRAST, 			GET_CONTRAST,			SET_CONTRAST},
+
+ {PD_ATTR_ID_HORZ_OVERSCAN, 	MAKE_NAME("Horz Overscan"),			2,
+  GET_MAX_HORIZONTAL_OVERSCAN,  GET_HORIZONTAL_OVERSCAN,SET_HORIZONTAL_OVERSCAN},
+
+ {PD_ATTR_ID_VERT_OVERSCAN, 	MAKE_NAME("Vert Overscan"),			2,
+  GET_MAX_VERTICAL_OVERSCAN,	GET_VERTICAL_OVERSCAN,	SET_VERTICAL_OVERSCAN},
+
+ {PD_ATTR_ID_HPOSITION, 		MAKE_NAME("Horz Position"),			2,
+  GET_MAX_HORIZONTAL_POSITION,  GET_HORIZONTAL_POSITION,SET_HORIZONTAL_POSITION},
+
+ {PD_ATTR_ID_VPOSITION, 		MAKE_NAME("Vert Position"),			2,
+  GET_MAX_VERTICAL_POSITION,	GET_VERTICAL_POSITION,	SET_VERTICAL_POSITION},
+
+ {PD_ATTR_ID_SHARPNESS, 		MAKE_NAME("Sharpness"),				2,
+  GET_MAX_SHARPNESS,			GET_SHARPNESS,			SET_SHARPNESS},
+
+ {PD_ATTR_ID_CHROMA_FILTER, 	MAKE_NAME("TV Chroma Filter"), 		2,
+  GET_MAX_TV_CHROMA_FILTER, 	GET_TV_CHROMA_FILTER,	SET_TV_CHROMA_FILTER},
+
+ {PD_ATTR_ID_LUMA_FILTER,		MAKE_NAME("TV Luma Filter"),		2,
+  GET_MAX_TV_LUMA_FILTER,		GET_TV_LUMA_FILTER, 	SET_TV_LUMA_FILTER},
+
+ {PD_ATTR_ID_ADAPTIVE_FLICKER,	MAKE_NAME("Adaptive Flicker Filter"),	2,
+  GET_MAX_ADAPTIVE_FLICKER_FILTER, GET_ADAPTIVE_FLICKER_FILTER, SET_ADAPTIVE_FLICKER_FILTER},
+
+ {PD_ATTR_ID_SSC,				MAKE_NAME("Spread Spectrum Clocking"), 1,
+  GET_MAX_SSC,					GET_SSC,				SET_SSC},
+#endif
+};
+
+
+/* .......................................................................... */
+static sdvo_bool_attr_data_t g_bool_data[] =
+/*	ID								Name					Bit_Mask_Cur	Bit_Mask_Def	 */
+/*	opcode_get				opcode_set */
+{
+ {PD_ATTR_ID_2_CHANNEL_PANEL, MAKE_NAME("Dual Channel"),    0x10,           0,
+  GET_LVDS_PANEL_INFORMATION, SET_LVDS_PANEL_INFORMATION},
+
+ /* 0-spwg, 1-openldi */
+ {PD_ATTR_ID_LVDS_PANEL_TYPE, MAKE_NAME("LVDS Panel Type"), 0x04,	        0,
+  GET_LVDS_PANEL_INFORMATION, SET_LVDS_PANEL_INFORMATION},
+
+ {PD_ATTR_ID_DITHER,          MAKE_NAME("Dither"),          0x01,        0x02,
+  GET_DITHER,                 SET_DITHER},
+
+#ifndef CONFIG_MICRO
+ {PD_ATTR_ID_DOT_CRAWL,     MAKE_NAME("Dot Crawl"),							0x01,	0x02,
+  GET_DOT_CRAWL,			SET_DOT_CRAWL},
+
+ {PD_ATTR_ID_PANEL_PROTECT_HSYNC,	MAKE_NAME("HSync Panel Protection"),	0x01,	0,
+  GET_LVDS_PANEL_PROTECTION, SET_LVDS_PANEL_PROTECTION},
+
+ {PD_ATTR_ID_PANEL_PROTECT_VSYNC,	MAKE_NAME("VSync Panel Protection"),	0x02,	0,
+  GET_LVDS_PANEL_PROTECTION, SET_LVDS_PANEL_PROTECTION},
+
+ {PD_ATTR_ID_PANEL_PROTECT_PIXCLK,	MAKE_NAME("Pixel Clock Protection"),	0x04,	0,
+  GET_LVDS_PANEL_PROTECTION, SET_LVDS_PANEL_PROTECTION},
+#endif
+};
+
+/* .......................................................................... */
+#ifndef CONFIG_MICRO
+/* List entries for the TV format, the header are in g_list_header[] */
+static sdvo_attr_list_entry_t g_list_entry_tv_format[] =
+{
+	{PD_TV_STD_NTSC_M,   MAKE_NAME("NTSC_M"),   0, 0x01},
+	{PD_TV_STD_NTSC_M_J, MAKE_NAME("NTSC_J"),   0, 0x02},
+	{PD_TV_STD_NTSC_433, MAKE_NAME("NTSC_433"),	0, 0x04},
+	{PD_TV_STD_PAL_B,    MAKE_NAME("PAL_B"),    0, 0x08},
+	{PD_TV_STD_PAL_D,    MAKE_NAME("PAL_D"),    0, 0x10},
+	{PD_TV_STD_PAL_G,    MAKE_NAME("PAL_G"),    0, 0x20},
+	{PD_TV_STD_PAL_H,    MAKE_NAME("PAL_H"),    0, 0x40},
+	{PD_TV_STD_PAL_I,    MAKE_NAME("PAL_I"),    0, 0x80},
+
+	{PD_TV_STD_PAL_M,   MAKE_NAME("PAL_M"),     1, 0x01},
+	{PD_TV_STD_PAL_N,   MAKE_NAME("PAL_N"),     1, 0x02},
+	{PD_TV_STD_PAL_NC,  MAKE_NAME("PAL_NC"),    1, 0x04},
+	{PD_TV_STD_PAL_60,  MAKE_NAME("PAL_60"),    1, 0x08},
+	{PD_TV_STD_SECAM_B,	MAKE_NAME("SECAM_B"),   1, 0x10},
+	{PD_TV_STD_SECAM_D,	MAKE_NAME("SECAM_D"),   1, 0x20},
+	{PD_TV_STD_SECAM_G,	MAKE_NAME("SECAM_G"),   1, 0x40},
+	{PD_TV_STD_SECAM_K,	MAKE_NAME("SECAM_K"),   1, 0x80},
+
+	{PD_TV_STD_SECAM_K1, MAKE_NAME("SECAM_K1"), 2, 0x01},
+	{PD_TV_STD_SECAM_L,  MAKE_NAME("SECAM_L"),  2, 0x02},
+	{PD_TV_STD_SECAM_60, MAKE_NAME("SECAM_60"), 2, 0x04},
+
+	{PD_HDTV_STD_SMPTE_240M_1080i59, MAKE_NAME("SMPTE_240M_1080i59"), 2, 0x08},
+	{PD_HDTV_STD_SMPTE_240M_1080i60, MAKE_NAME("SMPTE_240M_1080i60"), 2, 0x10},
+	{PD_HDTV_STD_SMPTE_260M_1080i59, MAKE_NAME("SMPTE_260M_1080i59"), 2, 0x20},
+	{PD_HDTV_STD_SMPTE_260M_1080i60, MAKE_NAME("SMPTE_260M_1080i60"), 2, 0x40},
+	{PD_HDTV_STD_SMPTE_274M_1080i50, MAKE_NAME("SMPTE_274M_1080i50"), 2, 0x80},
+
+	{PD_HDTV_STD_SMPTE_274M_1080i59, MAKE_NAME("SMPTE_274M_1080i59"), 3, 0x01},
+	{PD_HDTV_STD_SMPTE_274M_1080i60, MAKE_NAME("SMPTE_274M_1080i60"), 3, 0x02},
+	{PD_HDTV_STD_SMPTE_274M_1080p23, MAKE_NAME("SMPTE_274M_1080p23"), 3, 0x04},
+	{PD_HDTV_STD_SMPTE_274M_1080p24, MAKE_NAME("SMPTE_274M_1080p24"), 3, 0x08},
+	{PD_HDTV_STD_SMPTE_274M_1080p25, MAKE_NAME("SMPTE_274M_1080p25"), 3, 0x10},
+	{PD_HDTV_STD_SMPTE_274M_1080p29, MAKE_NAME("SMPTE_274M_1080p29"), 3, 0x20},
+	{PD_HDTV_STD_SMPTE_274M_1080p30, MAKE_NAME("SMPTE_274M_1080p30"), 3, 0x40},
+	{PD_HDTV_STD_SMPTE_274M_1080p50, MAKE_NAME("SMPTE_274M_1080p50"), 3, 0x80},
+
+	{PD_HDTV_STD_SMPTE_274M_1080p59, MAKE_NAME("SMPTE_274M_1080p59"), 4, 0x01},
+	{PD_HDTV_STD_SMPTE_274M_1080p60, MAKE_NAME("SMPTE_274M_1080p60"), 4, 0x02},
+	{PD_HDTV_STD_SMPTE_295M_1080i50, MAKE_NAME("SMPTE_295M_1080i50"), 4, 0x04},
+	{PD_HDTV_STD_SMPTE_295M_1080p50, MAKE_NAME("SMPTE_295M_1080p50"), 4, 0x08},
+	{PD_HDTV_STD_SMPTE_296M_720p59,  MAKE_NAME("SMPTE_296M_720p59"),  4, 0x10},
+	{PD_HDTV_STD_SMPTE_296M_720p60,  MAKE_NAME("SMPTE_296M_720p60"),  4, 0x20},
+	{PD_HDTV_STD_SMPTE_296M_720p50,  MAKE_NAME("SMPTE_296M_720p50"),  4, 0x40},
+	{PD_HDTV_STD_SMPTE_293M_480p59,  MAKE_NAME("SMPTE_293M_480p59"),  4, 0x80},
+
+	{PD_HDTV_STD_SMPTE_170M_480i59,  MAKE_NAME("MPTE_170M_480i59"),   5, 0x01},
+	{PD_HDTV_STD_ITURBT601_576i50,   MAKE_NAME("ITURBT601_576i50"),   5, 0x02},
+	{PD_HDTV_STD_ITURBT601_576p50,   MAKE_NAME("TURBT601_576p50"),    5, 0x04},
+	{PD_HDTV_STD_EIA_7702A_480i60,   MAKE_NAME("EIA_7702A_480i60"),   5, 0x08},
+	{PD_HDTV_STD_EIA_7702A_480p60,   MAKE_NAME("EIA_7702A_480p60"),   5, 0x10},
+	{0, NULL, 0, 0}
+};
+
+/* Enable below attributes once upper layers hooked up copyprotection API */
+
+/* List entries for the analog source, the header are in g_list_header[] */
+static sdvo_attr_list_entry_t g_list_entry_analog_src[] =
+{
+	{PD_ANALOG_SRC_NO_DATA,          MAKE_NAME("No Data"),                 0, 0x00},
+	{PD_ANALOG_SRC_PRE_RECORDED,     MAKE_NAME("Pre-recorded Packaged"),   0, 0x20},
+	{PD_ANALOG_SRC_NOT_PRE_RECORDED, MAKE_NAME("Not Analog Pre-recorded"), 0, 0x30},
+	{0, NULL, 0, 0}
+};
+
+/* List entries for the scan information, the header are in g_list_header[] */
+static sdvo_attr_list_entry_t g_list_entry_scan_info[] =
+{
+	{PD_SCAN_NO_DATA,      MAKE_NAME("No Data"),      0, 0x00},
+	{PD_SCAN_OVERSCANNED,  MAKE_NAME("Overscanned"),  0, 0x40},
+	{PD_SCAN_UNDERSCANNED, MAKE_NAME("Underscanned"), 0, 0x80},
+	{0, NULL, 0, 0}
+};
+
+/* List entries for the aspect ratio, the header are in g_list_header[] */
+static sdvo_attr_list_entry_t g_list_entry_aspect_ratio[] =
+{
+	{PD_SCAN_NO_DATA,      MAKE_NAME("No Data"), 1, 0x00},
+	{PD_SCAN_OVERSCANNED,  MAKE_NAME("4:3"),     1, 0x01},
+	{PD_SCAN_UNDERSCANNED, MAKE_NAME("16:9"),    1, 0x02},
+	{0, NULL, 0, 0}
+};
+
+/* List entries for the active format, the header are in g_list_header[] */
+static sdvo_attr_list_entry_t g_list_entry_active_format[] =
+{
+	{PD_ACTIVE_FORMAT_NO_DATA,
+	 MAKE_NAME("No Data"),                               1, 0x00},
+	{PD_ACTIVE_FORMAT_SQUARE_PIXELS,
+	 MAKE_NAME("Square Pixels"),                         1, 0x20},
+	{PD_ACTIVE_FORMAT_4_3_CENTER,
+	MAKE_NAME("4:3 Center"),                             1, 0x24},
+	{PD_ACTIVE_FORMAT_16_9_CENTER,
+	MAKE_NAME("16:9 Center"),                            1, 0x28},
+	{PD_ACTIVE_FORMAT_14_9_CENTER,
+	MAKE_NAME("14:9 Center"),                            1, 0x2C},
+	{PD_ACTIVE_FORMAT_16_9_LETTERBOX_TOP,
+	MAKE_NAME("16:9 Letterbox(Top)"),                    1, 0x08},
+	{PD_ACTIVE_FORMAT_14_9_LETTERBOX_TOP,
+	MAKE_NAME("14:9 Letterbox(Top)"),                    1, 0x0C},
+	{PD_ACTIVE_FORMAT_16_9_LETTERBOX_CENTER,
+	MAKE_NAME("16:9 Letterbox(Center)"),                 1, 0x10},
+	{PD_ACTIVE_FORMAT_4_3_SHOOT_PROTECT_14_9_CENTER,
+	MAKE_NAME("4:3(with shoot & protect 14:9 center)"),	 1, 0x34},
+	{PD_ACTIVE_FORMAT_16_9_SHOOT_PROTECT_14_9_CENTER,
+	MAKE_NAME("16:9(with shoot & protect 14:9 center)"), 1, 0x38},
+	{PD_ACTIVE_FORMAT_16_9_SHOOT_PROTECT_4_3_CENTER,
+	MAKE_NAME("16:9(with shoot & protect 4:3 center)"),	 1, 0x3C},
+	{0, NULL, 0, 0}
+};
+
+static sdvo_attr_list_header_t g_list_header[] =
+{
+	{45, PD_ATTR_ID_TVFORMAT, MAKE_NAME("TV Out Format"),
+	 GET_TV_OUTPUT_FORMAT, SET_TV_OUTPUT_FORMAT,
+	 {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	 g_list_entry_tv_format},
+
+/* Enable below attributes once upper layers hooked up copyprotection API */
+
+    { 3, PD_ATTR_ID_ANALOG_SRC, MAKE_NAME("Analog Source"),
+	 GET_ANCILLARY_VIDEO_INFORMATION, SET_ANCILLARY_VIDEO_INFORMATION,
+	 {0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	 g_list_entry_analog_src},
+
+	{ 3, PD_ATTR_ID_SCAN_INFO, MAKE_NAME("Scan Information"),
+	 GET_ANCILLARY_VIDEO_INFORMATION, SET_ANCILLARY_VIDEO_INFORMATION,
+	 {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	 g_list_entry_scan_info},
+
+	{ 3, PD_ATTR_ID_PICTURE_ASPECT_RATIO, MAKE_NAME("Picture Aspect Ratio"),
+	 GET_ANCILLARY_VIDEO_INFORMATION, SET_ANCILLARY_VIDEO_INFORMATION,
+	 {0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	 g_list_entry_aspect_ratio},
+
+	{11, PD_ATTR_ID_ACTIVE_FORMAT, MAKE_NAME("Active Format Aspect Ratio"),
+	 GET_ANCILLARY_VIDEO_INFORMATION, SET_ANCILLARY_VIDEO_INFORMATION,
+	 {0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	 g_list_entry_active_format},
+
+	{ 0 }
+};
+
+#endif
+
+#ifndef CONFIG_MICRO
+sdvo_status_t sdvo_set_tv_optimal_settings(sdvo_device_context_t *p_ctx,
+	unsigned char chron_tv_code)
+{
+
+	sdvo_status_t status = SS_SUCCESS;
+	pd_attr_t *p_attr;
+	int i;
+
+
+	for (i= 0;i <5;i ++)
+		if (chron_tv_code == g_sdtv_op_settings[i].tv_code) {
+			/* set hue */
+			p_attr = pd_get_attr(p_ctx->p_attr_table, p_ctx->num_attrs,
+					PD_ATTR_ID_HUE, 0);
+			if (NULL != p_attr)
+			{
+				status = sdvo_alter_range_attr(p_ctx, (pd_range_attr_t *)p_attr,
+						g_sdtv_op_settings[i].hue);
+				p_attr->current_value = g_sdtv_op_settings[i].hue; //update table
+			}
+
+			/* set saturation */
+			p_attr = pd_get_attr(p_ctx->p_attr_table, p_ctx->num_attrs,
+					PD_ATTR_ID_SATURATION, 0);
+			if (NULL != p_attr)
+			{
+				status = sdvo_alter_range_attr(p_ctx, (pd_range_attr_t *)p_attr,
+						g_sdtv_op_settings[i].saturation);
+
+				p_attr->current_value = g_sdtv_op_settings[i].saturation;
+			}
+
+			/* set brightness */
+			p_attr = pd_get_attr(p_ctx->p_attr_table, p_ctx->num_attrs,
+					PD_ATTR_ID_BRIGHTNESS, 0);
+			if (p_attr)
+			{
+				status = sdvo_alter_range_attr(p_ctx, (pd_range_attr_t *)p_attr,
+						g_sdtv_op_settings[i].brightness);
+
+				p_attr->current_value = g_sdtv_op_settings[i].brightness;
+			}
+
+			/* set contrast */
+			p_attr = pd_get_attr(p_ctx->p_attr_table, p_ctx->num_attrs,
+					PD_ATTR_ID_CONTRAST, 0);
+			if (p_attr)
+			{
+				status = sdvo_alter_range_attr(p_ctx, (pd_range_attr_t *)p_attr,
+						g_sdtv_op_settings[i].contrast);
+
+				p_attr->current_value = g_sdtv_op_settings[i].contrast;
+			}
+		}
+
+	return status;
+}
+#endif
+
+/* .......................................................................... */
+/* .......................................................................... */
+/*	============================================================================
+	Function	:	sdvo_get_static_attrs
+
+	Parameters	:	p_attr : Returns the list of avaliable static attributes
+
+	Remarks     :
+
+	Returns     :
+	------------------------------------------------------------------------- */
+unsigned long sdvo_get_static_attrs(sdvo_device_context_t *p_ctx,
+	pd_attr_t *p_attr_list1)
+{
+	int num_attrs = 0;
+	pd_range_attr_t *p_attr_list = (pd_range_attr_t *)p_attr_list1;
+
+	if (p_attr_list == NULL) {
+
+		/*	Just return the number of available attributes */
+
+		if (p_ctx->out_type.flags & FP_DISP_MASK) {
+			num_attrs ++;
+
+			/* Enable Text Tuning */
+			if ((p_ctx->out_type.flags & LVDS_DISP_MASK) &&
+				(p_ctx->dev_cap.up_scaling)) {
+				num_attrs++;
+			}
+		}
+
+		/*	Add Display Attribute only if sDVO returned more than one
+			display type from GetDeviceCapabilities */
+		if (sdvo_is_multi_display_device(p_ctx)) {
+			num_attrs++;
+		}
+
+		/*  Red Blue Swap for DRGB output */
+		if((p_ctx->out_type.flags & DRGB_DISP_MASK) && (p_ctx->dev_cap.vendor_id == 0x81)){
+			num_attrs++;
+		}
+		return num_attrs;
+	}
+
+	/* ...................................................................... */
+	/*	Fill in the available attributes */
+
+	/*	Width and Height Attributes are available for LVDS and TMDS only */
+	if (p_ctx->out_type.flags & FP_DISP_MASK) {
+		p_attr_list[num_attrs] = g_fp_attr[1];   /* PANELFIT */
+		/* There are initial values */
+		p_attr_list[num_attrs].current_value = p_ctx->dev_cap.up_scaling;
+		p_ctx->up_scaling = p_ctx->dev_cap.up_scaling;
+		num_attrs++;
+
+		/* Enable Text Tuning */
+		if ((p_ctx->out_type.flags & LVDS_DISP_MASK) &&
+			(p_ctx->dev_cap.up_scaling)) {
+			p_attr_list[num_attrs] = g_fp_attr[2];   /* Text tuning */
+			num_attrs++;
+		}
+	}
+
+	/*	Add Display Attribute only if sDVO returned more than one
+		display type from GetDeviceCapabilities */
+	if (sdvo_is_multi_display_device(p_ctx)) {
+		p_attr_list[num_attrs] = g_fp_attr[0];
+		p_attr_list[num_attrs].default_value = p_ctx->dev_cap.output.flags;
+		p_attr_list[num_attrs].current_value = p_ctx->out_type.flags;
+		num_attrs++;
+	}
+
+	/*  Red Blue Swap for DRGB output */
+	if((p_ctx->out_type.flags & DRGB_DISP_MASK) && (p_ctx->dev_cap.vendor_id == 0x81)){
+		p_attr_list[num_attrs] = g_fp_attr[3];
+		num_attrs++;
+	}
+
+
+#ifdef DEBUG_BUILD_TYPE
+	/* ...................................................................... */
+	{
+		int i;
+		for (i = 0; i < num_attrs; i++) {
+			pd_attr_t *p_attr_cur = (pd_attr_t *)&p_attr_list[i];
+			PD_DEBUG("sdvo : sdvo_get_static_attrs : "
+			  "Adding attr='%s', id=%ld, type=%ld, default=%ld, current=%ld",
+			  SDVO_GET_ATTR_NAME(p_attr_cur), p_attr_cur->id, p_attr_cur->type,
+			  p_attr_cur->default_value, p_attr_cur->current_value);
+		}
+	}
+#endif
+
+	/* ...................................................................... */
+	return num_attrs;
+}
+
+
+/*	============================================================================
+	Function	:	sdvo_query_static_attr
+
+	Parameters	:
+
+	Remarks     :
+
+	Returns     :
+	------------------------------------------------------------------------- */
+sdvo_status_t sdvo_query_static_attr(sdvo_device_context_t *p_ctx,
+	pd_attr_t *p_attr)
+{
+	int b_error = 1;
+	i2c_reg_t temp_reg;
+
+	switch (p_attr->id) {
+		case PD_ATTR_ID_DISPLAY :
+			p_attr->current_value = p_ctx->out_type.flags;
+			b_error = 0;
+			break;
+
+		case PD_ATTR_ID_PANEL_FIT:
+			if (p_ctx->out_type.flags & FP_DISP_MASK) {
+				p_attr->current_value = p_ctx->up_scaling;
+				b_error = 0;
+			}
+			break;
+
+		case PD_ATTR_ID_TEXT_TUNING:
+			p_attr->current_value = p_ctx->text_tune;
+			b_error = 0;
+			break;
+		case PD_ATTR_ID_RB_SWAP_MODE:
+			{
+				sdvo_read_i2c_reg(p_ctx, 0x30, &temp_reg);
+				if (!(p_attr->flags & PD_ATTR_FLAG_NEED_RESTORE)){
+					p_attr->current_value = (temp_reg & 0x2)?1:0;
+				}
+				/*Impossible to return correct value since the encoder
+				has been reset.*/
+
+				b_error = 0;
+			}
+			break;
+	}
+
+	/*	..................................................................... */
+	if (b_error) {
+
+		PD_ERROR("sdvo : Error ! sdvo_query_static_attr : "
+			"Invalid attr='%s, id=%ld",
+			SDVO_GET_ATTR_NAME(p_attr), p_attr->id);
+
+		return SS_INVALID_ARGUMENT;
+	}
+
+	return SS_SUCCESS;
+}
+
+
+/*	============================================================================
+	Function	:	sdvo_alter_static_attr
+
+	Parameters	:
+
+	Remarks     :
+
+	Returns     :
+	------------------------------------------------------------------------- */
+sdvo_status_t sdvo_alter_static_attr(sdvo_device_context_t *p_ctx,
+	pd_attr_t *p_attr, unsigned long new_value)
+{
+	int b_error = 1;
+	i2c_reg_t temp_reg;
+
+	switch (p_attr->id) {
+		case PD_ATTR_ID_PANEL_FIT:
+			if (p_ctx->out_type.flags & FP_DISP_MASK) {
+				p_ctx->up_scaling = (unsigned char)
+				((p_ctx->dev_cap.up_scaling)?new_value:0);
+				b_error = 0;
+			}
+			break;
+
+		case PD_ATTR_ID_TEXT_TUNING:
+			if (sdvo_set_upscalar_coefficient(p_ctx,(i2c_reg_t)new_value) ==
+				SS_SUCCESS) {
+				p_ctx->text_tune = (i2c_reg_t)new_value;
+			}
+			b_error = 0;
+			break;
+		case PD_ATTR_ID_RB_SWAP_MODE:
+			sdvo_read_i2c_reg(p_ctx, 0x30, &temp_reg);
+			if(new_value){
+				temp_reg |= 0x2;
+				p_attr->current_value = 1;
+			}else{
+				temp_reg &= ~(0x2);
+				p_attr->current_value = 0;
+			}
+			p_attr->flags |= PD_ATTR_FLAG_SETMODE;
+			p_attr->flags &= ~PD_ATTR_FLAG_NEED_RESTORE;
+			sdvo_write_i2c_reg(p_ctx, 0x30, temp_reg);
+			b_error = 0;
+			break;
+	}
+
+	/*	..................................................................... */
+	if (b_error) {
+		PD_ERROR("sdvo : Error ! sdvo_alter_static_attr : "
+			"Invalid attr='%s, id=%ld",
+			SDVO_GET_ATTR_NAME(p_attr), p_attr->id);
+		return SS_INVALID_ARGUMENT;
+	}
+	return SS_SUCCESS;
+}
+
+
+/*	============================================================================
+	Function	:	sdvo_get_panel_pwr_seq_attrs
+
+	Parameters	:	pp_Attr : Returns the list of avaliable attributes
+
+	Remarks     :
+
+	Returns     :
+	------------------------------------------------------------------------- */
+unsigned long sdvo_get_panel_pwr_seq_attrs(sdvo_device_context_t *p_ctx,
+	pd_range_attr_t *p_attr)
+{
+	sdvo_status_t status;
+	i2c_reg_t ret_val[8];
+	int i;
+
+	status = sdvo_execute_command(p_ctx,
+		GET_MAX_PANEL_POWER_SEQUENCING_PARAMETER,
+		0, NULL,
+		7, ret_val);
+	if (status != SS_SUCCESS) {
+		return 0;
+	}
+
+	if (p_attr == NULL) {
+		/*	Just return the number of available attributes */
+		return ARRAY_SIZE(g_panel_power_attr);
+	}
+
+	/* ...................................................................... */
+	g_panel_power_attr[0].max=((unsigned long)(ret_val[5]&0x03)<<8)|ret_val[0];
+	g_panel_power_attr[1].max=((unsigned long)(ret_val[5]&0x0C)<<6)|ret_val[1];
+	g_panel_power_attr[2].max=((unsigned long)(ret_val[5]&0x30)<<4)|ret_val[2];
+	g_panel_power_attr[3].max=((unsigned long)(ret_val[5]&0xC0)<<2)|ret_val[3];
+	g_panel_power_attr[4].max=((unsigned long)(ret_val[6]&0x03)<<8)|ret_val[4];
+
+	for (i = 0; i < 5; i++)	{
+		pd_range_attr_t *p_attr_cur = &g_panel_power_attr[i];
+		p_attr_cur->flags |= PD_ATTR_FLAG_DYNAMIC;
+#ifndef CONFIG_MICRO
+		status = sdvo_query_panel_pwr_seq_attr(p_ctx, p_attr_cur);
+		if (status != SS_SUCCESS) {
+			return 0;
+		}
+		p_attr_cur->default_value = p_attr_cur->current_value;
+#endif
+		PD_DEBUG("sdvo : sdvo_get_panel_pwr_seq_attrs : "
+		  "Adding attr='%s', id=%ld, default=%ld, current=%ld, min=%ld, "
+		  "max=%ld, step=%ld",
+		  SDVO_GET_ATTR_NAME(p_attr_cur), p_attr_cur->id,
+		  p_attr_cur->default_value, p_attr_cur->current_value,
+		  p_attr_cur->min, p_attr_cur->max, p_attr_cur->step);
+
+	}
+
+	pd_memcpy(p_attr, g_panel_power_attr, sizeof(g_panel_power_attr));
+	return ARRAY_SIZE(g_panel_power_attr);
+}
+
+
+/*	============================================================================
+	Function	:
+
+	Parameters	:
+
+	Remarks     :
+
+	Returns     :
+	------------------------------------------------------------------------- */
+sdvo_status_t sdvo_query_panel_pwr_seq_attr(sdvo_device_context_t *p_ctx,
+	pd_range_attr_t *p_attr)
+{
+#ifndef CONFIG_MICRO
+	sdvo_status_t status;
+	i2c_reg_t ret_val[8];
+
+	status = sdvo_execute_command(p_ctx, GET_PANEL_POWER_SEQUENCING_PARAMETER,
+								 0, NULL,
+								 7, ret_val);
+	if (status != SS_SUCCESS) {
+
+		return status;
+	}
+
+	switch (p_attr->id) {
+
+		case PD_ATTR_ID_FP_PWR_T1 :
+			p_attr->current_value = p_ctx->t1 =
+				((unsigned short)(ret_val[5] & 0x03) << 8) | ret_val[0];
+			break;
+
+		case PD_ATTR_ID_FP_PWR_T2 :
+			p_attr->current_value = p_ctx->t2 =
+				((unsigned short)(ret_val[5] & 0x0C) << 6) | ret_val[1];
+			break;
+
+		case PD_ATTR_ID_FP_PWR_T3 :
+			p_attr->current_value = p_ctx->t3 =
+				((unsigned short)(ret_val[5] & 0x30) << 4) | ret_val[2];
+			break;
+
+		case PD_ATTR_ID_FP_PWR_T4 :
+			p_attr->current_value = p_ctx->t4 =
+				((unsigned short)(ret_val[5] & 0xC0) << 2) | ret_val[3];
+			break;
+
+		case PD_ATTR_ID_FP_PWR_T5 :
+			p_attr->current_value = p_ctx->t5 =
+				((unsigned short)(ret_val[6] & 0x03) << 8) | ret_val[4];
+			break;
+
+		default :
+			return SS_INVALID_ARGUMENT;
+	}
+#endif
+	return SS_SUCCESS;
+}
+
+
+/*	============================================================================
+	Function	:	sdvo_alter_panel_pwr_seq_attr
+
+	Parameters	:
+
+	Remarks     :
+
+	Returns     :
+	------------------------------------------------------------------------- */
+sdvo_status_t sdvo_alter_panel_pwr_seq_attr(sdvo_device_context_t *p_ctx,
+	pd_range_attr_t *p_attr,
+	unsigned long new_value)
+{
+	sdvo_status_t status;
+	i2c_reg_t arg[8];
+	i2c_reg_t new_val_low  = (i2c_reg_t)(new_value & 0xFF);
+	i2c_reg_t new_val_high = (i2c_reg_t)((new_value & 0x0300) >> 8);
+
+	if ((new_value < p_attr->min) || (new_value > p_attr->max)) {
+		PD_DEBUG("Requested values out of range, new_value = %lu.",
+			new_value);
+		return SS_INVALID_ARGUMENT;
+	}
+
+	status = sdvo_execute_command(p_ctx, GET_PANEL_POWER_SEQUENCING_PARAMETER,
+		0, NULL, 7, arg);
+	if (status != SS_SUCCESS) {
+		PD_DEBUG("GET_PANEL_POWER_SEQUENCING_PARAMETER failed status = %u",
+			status);
+		return status;
+	}
+
+	switch (p_attr->id) {
+		case PD_ATTR_ID_FP_PWR_T1 :
+			p_ctx->t1 = (unsigned short)new_value;
+			arg[0] = new_val_low;
+			arg[5] &= 0xFC;
+			arg[5] |= new_val_high;
+			break;
+
+		case PD_ATTR_ID_FP_PWR_T2 :
+			p_ctx->t2 = (unsigned short)new_value;
+			arg[1] = new_val_low;
+			arg[5] &= 0xF3;
+			arg[5] |= (new_val_high << 2);
+			break;
+
+		case PD_ATTR_ID_FP_PWR_T3 :
+			p_ctx->t3 = (unsigned short)new_value;
+			arg[2] = new_val_low;
+			arg[5] &= 0xCF;
+			arg[5] |= (new_val_high << 4);
+			break;
+
+		case PD_ATTR_ID_FP_PWR_T4 :
+			p_ctx->t4 = (unsigned short)new_value;
+			arg[3] = new_val_low;
+			arg[5] &= 0x3F;
+			arg[5] |= (new_val_high << 6);
+			break;
+
+		case PD_ATTR_ID_FP_PWR_T5 :
+			p_ctx->t5 = (unsigned short)new_value;
+			arg[4] = new_val_low;
+			arg[6] &= 0xFC;
+			arg[6] |= new_val_high;
+			break;
+
+		default :
+			return SS_INVALID_ARGUMENT;
+	}
+
+	status = sdvo_execute_command(p_ctx, SET_PANEL_POWER_SEQUENCING_PARAMETER,
+								 7, arg,
+								 0, NULL);
+	return status;
+}
+
+
+/*	============================================================================
+	Function	:	sdvo_get_range_attrs returns all the available range
+					attributes
+
+	Parameters	:	pp_Attr : Returns the list of avaliable range attributes
+
+	Remarks     :	sdvo_get_range_attrs returns all the range attributes
+					from g_range_data table that are supported by the SDVO device.
+					It allocates memory for all possible range attributes.
+					The caller is responsible for adding the range attributes to
+					port driver attribute table and freeing the memory allocated
+					for pp_Attr.
+
+	Returns     :	Number of range attributes returned in pp_Attr list.
+	------------------------------------------------------------------------- */
+unsigned long sdvo_get_range_attrs(sdvo_device_context_t *p_ctx,
+	pd_range_attr_t *p_attr)
+{
+	unsigned long num_attrs, i;
+	sdvo_status_t status;
+	unsigned char byte_ret[4];
+
+	/*	..................................................................... */
+	if (p_attr == NULL) {
+		/*	Just return the number of available attributes */
+		num_attrs = 0;
+
+		for (i = 0; i < ARRAY_SIZE(g_range_data); i++) {
+			status = sdvo_execute_command(p_ctx, g_range_data[i].opcode_max,
+							0, NULL,
+							(i2c_reg_t)(g_range_data[i].num_bytes * 2),
+							byte_ret);
+			if (status != SS_SUCCESS) {
+				continue;
+			}
+
+			status = sdvo_execute_command(p_ctx, g_range_data[i].opcode_get,
+										 0, NULL,
+										 (i2c_reg_t)(g_range_data[i].num_bytes),
+										 byte_ret);
+			if (status != SS_SUCCESS) {
+				continue;
+			}
+
+			num_attrs++;
+		}
+
+		return num_attrs;
+	}
+
+	/*	..................................................................... */
+	num_attrs = 0;
+
+	for (i = 0; i < ARRAY_SIZE(g_range_data); i++) {
+
+		pd_range_attr_t *p_attr_cur = &p_attr[num_attrs];
+
+		status = sdvo_execute_command(p_ctx, g_range_data[i].opcode_max,
+									 0, NULL,
+									 (i2c_reg_t)(g_range_data[i].num_bytes * 2),
+									 byte_ret);
+		if (status != SS_SUCCESS) {
+
+			continue;
+		}
+
+		p_attr_cur->id = g_range_data[i].id;
+		p_attr_cur->type = PD_ATTR_TYPE_RANGE;
+		p_attr_cur->flags |= PD_ATTR_FLAG_DYNAMIC;
+
+#ifndef CONFIG_MICRO
+		pd_strcpy(p_attr_cur->name, g_range_data[i].p_name);
+#endif
+
+		p_attr_cur->default_value = g_range_data[i].num_bytes == 1 ?
+									byte_ret[1] : byte_ret[2] + (byte_ret[3] << 8);
+		p_attr_cur->min	= 0;
+		p_attr_cur->step = 1;
+		p_attr_cur->max	= g_range_data[i].num_bytes == 1 ?
+			byte_ret[0] : byte_ret[0] + (byte_ret[1] << 8);
+
+		status = sdvo_query_range_attr(p_ctx, p_attr_cur);
+		if (status != SS_SUCCESS) {
+			continue;
+		}
+
+		PD_DEBUG("sdvo : sdvo_get_range_attrs : "
+				  "Adding attr='%s', id=%ld, default=%ld, current=%ld, min=%ld, "
+				  "max=%ld, step=%ld",
+				  SDVO_GET_ATTR_NAME(p_attr_cur), p_attr_cur->id,
+				  p_attr_cur->default_value, p_attr_cur->current_value,
+				  p_attr_cur->min, p_attr_cur->max, p_attr_cur->step);
+
+		num_attrs++;
+	}
+
+	/*	..................................................................... */
+	return num_attrs;
+}
+
+
+/*	============================================================================
+	Function	:	sdvo_query_range_attr is called to query the current value
+					of a specific range attribute
+
+	Parameters	:	p_attr : Pointer to range attribute
+
+	Remarks     :	sdvo_query_range_attr scans the g_range_data list to find
+					the range attribute of id specified in p_attr.
+					If found it executes the opcode_get command to get the current
+					value of the attribute.
+
+	Returns     :	sdvo_status_t : Status of command execution
+	------------------------------------------------------------------------- */
+sdvo_status_t sdvo_query_range_attr(sdvo_device_context_t *p_ctx,
+	pd_range_attr_t *p_attr)
+{
+	int i;
+	sdvo_status_t status;
+
+	for (i = 0; i < ARRAY_SIZE(g_range_data); i++) {
+
+		if (g_range_data[i].id == p_attr->id) {
+
+			status = sdvo_execute_command(p_ctx, g_range_data[i].opcode_get,
+									   0, NULL,
+									   g_range_data[i].num_bytes,
+									   (unsigned char *)&p_attr->current_value);
+
+			if (status == SS_SUCCESS) {
+				/* Special case for Panel depth */
+				if (g_range_data[i].id == PD_ATTR_ID_PANEL_DEPTH) {
+					p_attr->min = 18;
+					p_attr->step = 6;
+					p_attr->max = 24;
+					p_attr->default_value = 18;
+					if (p_attr->current_value & 0x01) {
+						p_attr->current_value = 24;
+					} else {
+						p_attr->current_value = 18;
+					}
+				}
+			}
+			return status;
+		}
+	}
+
+	return SS_INVALID_ARGUMENT;
+}
+
+
+/*	============================================================================
+	Function	:	sdvo_alter_range_attr is called to set the new value of a
+					specific range attribute
+
+	Parameters	:	p_attr : Pointer to range attribute
+
+	Remarks     :	sdvo_query_range_attr scans the g_range_data list to find
+					the range attribute of id specified in p_attr.
+					If found it executes the opcode_set command to set the new
+					value of the attribute.
+
+	Returns     :	sdvo_status_t : Status of command execution
+	------------------------------------------------------------------------- */
+sdvo_status_t sdvo_alter_range_attr(sdvo_device_context_t *p_ctx,
+	pd_range_attr_t *p_attr, unsigned long new_value)
+{
+	int i;
+	sdvo_status_t status;
+
+
+	if ((new_value < p_attr->min) || (new_value > p_attr->max)) {
+
+		return SS_INVALID_ARGUMENT;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(g_range_data); i++) {
+
+		if (g_range_data[i].id == p_attr->id) {
+			/* Special case handling for panel depth attribute */
+			if (p_attr->id == PD_ATTR_ID_PANEL_DEPTH) {
+				i2c_reg_t cur_value;
+				status = sdvo_execute_command(p_ctx,
+					g_range_data[i].opcode_get,
+					0, NULL,
+					1, &cur_value);
+				if (status != SS_SUCCESS) {
+					return status;
+				}
+
+				if (new_value == 24) {
+					/* 24-bit display */
+					new_value = cur_value | 0x01; /* set bits [1:0] = 01 */
+				} else {
+					/* 18-bit display */
+					new_value = cur_value & 0xFC; /* set bits [1:0] = 00 */
+				}
+			}
+
+			/*Special case handling for CH7308 EMI on/off operation */
+
+			if (p_attr->id == PD_ATTR_ID_SSC) {
+
+				i2c_reg_t reg;
+				if( new_value > 0) /* turn on EMI for value range from 1 - 15 */
+				{
+
+					sdvo_read_i2c_reg(p_ctx, 0x3C, &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/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.h b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.h
new file mode 100644
index 0000000..4c58315
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_attr.h
@@ -0,0 +1,141 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sdvo_attr.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Definitions for display attribute
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _SDVO_ATTR_H_
+#define _SDVO_ATTR_H_
+
+unsigned long sdvo_get_static_attrs(sdvo_device_context_t *p_ctx,   pd_attr_t *p_attr);
+sdvo_status_t sdvo_query_static_attr(sdvo_device_context_t *p_ctx,  pd_attr_t *p_attr);
+sdvo_status_t sdvo_alter_static_attr(sdvo_device_context_t *p_ctx,  pd_attr_t *p_attr,
+	unsigned long new_value);
+
+unsigned long sdvo_get_panel_pwr_seq_attrs(sdvo_device_context_t *p_ctx,   pd_range_attr_t *p_attr);
+sdvo_status_t sdvo_query_panel_pwr_seq_attr(sdvo_device_context_t *p_ctx,  pd_range_attr_t *p_attr);
+sdvo_status_t sdvo_alter_panel_pwr_seq_attr(sdvo_device_context_t *p_ctx,  pd_range_attr_t *p_attr,
+	unsigned long new_value);
+
+unsigned long sdvo_get_range_attrs(sdvo_device_context_t *p_ctx,   pd_range_attr_t *p_attr);
+sdvo_status_t sdvo_query_range_attr(sdvo_device_context_t *p_ctx,  pd_range_attr_t *p_attr);
+sdvo_status_t sdvo_alter_range_attr(sdvo_device_context_t *p_ctx,  pd_range_attr_t *p_attr,
+	unsigned long new_value);
+
+unsigned long sdvo_get_bool_attrs(sdvo_device_context_t *p_ctx,   pd_bool_attr_t *p_attr);
+sdvo_status_t sdvo_query_bool_attr(sdvo_device_context_t *p_ctx,  pd_bool_attr_t *p_attr);
+sdvo_status_t sdvo_alter_bool_attr(sdvo_device_context_t *p_ctx,  pd_bool_attr_t *p_attr,
+	unsigned long new_value);
+
+unsigned long sdvo_get_list_attrs(sdvo_device_context_t *p_ctx,   pd_list_attr_t *p_attr);
+sdvo_status_t sdvo_query_list_attr(sdvo_device_context_t *p_ctx,  pd_list_attr_t *p_attr);
+sdvo_status_t sdvo_alter_list_attr(sdvo_device_context_t *p_ctx,  pd_list_attr_t *p_attr,
+	unsigned long new_value);
+
+#ifndef CONFIG_MICRO
+sdvo_status_t sdvo_set_tv_optimal_settings(sdvo_device_context_t *p_ctx, unsigned char chron_tv_code);
+#endif
+
+/*	.......................................................................... */
+/*	Attribute Definitions */
+
+typedef struct {
+
+	unsigned long id;
+	char *p_name;
+	unsigned char num_bytes;
+	unsigned char opcode_max, opcode_get, opcode_set;
+
+} sdvo_range_attr_data_t;
+
+typedef struct {
+
+	unsigned long id;
+	char *p_name;
+	unsigned char bit_mask_cur, bit_mask_def;
+	unsigned char opcode_get, opcode_set;
+
+} sdvo_bool_attr_data_t;
+
+typedef struct {
+	unsigned long id;
+	char *p_name;
+	unsigned char reg_offset;
+	unsigned char value;
+} sdvo_attr_list_entry_t;
+
+typedef struct {
+	unsigned char num_entries;
+	unsigned long id;
+	char *p_name;
+	unsigned char opcode_get, opcode_set;
+	unsigned char bit_masks[8];
+	sdvo_attr_list_entry_t *attr_list;
+} sdvo_attr_list_header_t;
+
+#ifndef CONFIG_MICRO
+typedef struct {
+	unsigned char tv_code;
+	unsigned char hue;
+	unsigned char saturation;
+	unsigned char brightness;
+	unsigned char contrast;
+} sdvo_tv_optimal_settings_t;
+#endif
+
+#define PD_LVDS_COLOR_DEPTH_18	0
+#define PD_LVDS_COLOR_DEPTH_24	1
+
+#define PD_LVDS_CONNECTOR_SPWG		0
+#define PD_LVDS_CONNECTOR_OPEN_LDI	1
+
+#define PD_ANALOG_SRC_NO_DATA			0
+#define PD_ANALOG_SRC_PRE_RECORDED		2
+#define PD_ANALOG_SRC_NOT_PRE_RECORDED	3
+
+#define PD_SCAN_NO_DATA 		0
+#define PD_SCAN_OVERSCANNED 	1
+#define PD_SCAN_UNDERSCANNED	2
+
+#define PD_ASPECT_RATIO_NO_DATA 0
+#define PD_ASPECT_RATIO_4_3 	1
+#define PD_ASPECT_RATIO_16_9	2
+
+#define PD_ACTIVE_FORMAT_NO_DATA							0
+#define PD_ACTIVE_FORMAT_SQUARE_PIXELS						8
+#define PD_ACTIVE_FORMAT_4_3_CENTER 						9
+#define PD_ACTIVE_FORMAT_16_9_CENTER						10
+#define PD_ACTIVE_FORMAT_14_9_CENTER						11
+#define PD_ACTIVE_FORMAT_16_9_LETTERBOX_TOP 				2
+#define PD_ACTIVE_FORMAT_14_9_LETTERBOX_TOP 				3
+#define PD_ACTIVE_FORMAT_16_9_LETTERBOX_CENTER				4
+#define PD_ACTIVE_FORMAT_4_3_SHOOT_PROTECT_14_9_CENTER		13
+#define PD_ACTIVE_FORMAT_16_9_SHOOT_PROTECT_14_9_CENTER 	14
+#define PD_ACTIVE_FORMAT_16_9_SHOOT_PROTECT_4_3_CENTER		15
+
+#endif	/*	_SDVO_ATTR_H_ */
diff --git a/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.c b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.c
new file mode 100644
index 0000000..81dd8f7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.c
@@ -0,0 +1,524 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sdvo_hdmi.c
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Port driver HDMI interface functions
+ *-----------------------------------------------------------------------------
+ */
+
+#include "sdvo_hdmi.h"
+
+#if 0
+ /*	HDMI Attributes
+	Currently if omitting out this attributes as this should NOT be avalable
+	to user
+	TODO: Integrate this attributes into HDMI  */
+/* HDMI attributes */
+#define PD_HDMI_COLORIMETRY_256_RGB					0
+#define PD_HDMI_COLORIMETRY_220_RGB					1
+#define PD_HDMI_COLORIMETRY_422_YCRCB				2
+#define PD_HDMI_COLORIMETRY_444_YCRCB				3
+
+#define PD_HDMI_PIXEL_REPLICATION_1X_REPITION				1
+#define PD_HDMI_PIXEL_REPLICATION_2X_REPITION				2
+#define PD_HDMI_PIXEL_REPLICATION_4X_REPITION				4
+/-----------------------------------------------------------------------------/
+ {PD_ATTR_ID_COLORIMETRY, MAKE_NAME("Colorimetry"), {4}, {0x0F},
+  GET_CURRENT_COLORIMETRY, SET_CURRENT_COLORIMETRY},
+
+  /* 256 RGB is passthrough, real value is 0x01 but 0x00 works as well
+	and upon boot up the value is 0x00 */
+ {PD_HDMI_COLORIMETRY_256_RGB,
+  MAKE_NAME("RGB 256 level"),							{0}, {0x00}, 0, 0},
+ {PD_HDMI_COLORIMETRY_220_RGB,
+  MAKE_NAME("RGB 220 level"),							{0}, {0x02}, 0, 0},
+ {PD_HDMI_COLORIMETRY_422_YCRCB,
+  MAKE_NAME("4:2:2 YcrCb"),							{0}, {0x04}, 0, 0},
+ {PD_HDMI_COLORIMETRY_444_YCRCB,
+  MAKE_NAME("4:4:4 YcrCb"),							{0}, {0x08}, 0, 0},
+
+ {PD_ATTR_ID_PIXEL_REPLICATION, MAKE_NAME("Pixel Replication"), {3}, {0x1F},
+  GET_PIXEL_REPLICATION, SET_PIXEL_REPLICATION},
+
+ {PD_HDMI_PIXEL_REPLICATION_1X_REPITION,
+  MAKE_NAME("No Repetition"),							{0}, {0x00}, 0, 0},
+ {PD_HDMI_PIXEL_REPLICATION_2X_REPITION,
+  MAKE_NAME("1X Repetition"),							{0}, {0x01}, 0, 0},
+ {PD_HDMI_PIXEL_REPLICATION_4X_REPITION,
+  MAKE_NAME("3X Repetition"),							{0}, {0x03}, 0, 0},
+#endif
+#if defined(SDVO_HDMI)
+
+/*	============================================================================
+	Function	:	sdvo_hdmi_transmitter
+
+	Parameters	:
+
+	Remarks 	:	Detect if transmitter is a HDMI transmitter.
+
+	Returns 	:
+	------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_transmitter(sdvo_device_context_t *p_ctx)
+{
+	return sdvo_get_supported_encoding_modes(p_ctx,&(p_ctx->hdmi.version));
+}
+
+/*	============================================================================
+	Function	:	sdvo_hdmi_support is called to see if the transmitter
+					and the monitor device support HDMI.
+
+	Parameters	:	p_context: Pointer to port driver allocated context
+								structure
+
+	Remarks 	:
+
+	Returns 	:	sdvo_status_t : Status of command execution
+	------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_support(void *p_context)
+{
+	sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+	sdvo_status_t status = SS_SUCCESS;
+
+	/* Monitor support is determined by valid CEA 861 extension and */
+	/* vendor block with 0xC03 IEEE regstration ID */
+	/*
+	if((p_ctx->p_callback->eld) == NULL){
+		return SS_NOT_SUPPORTED;
+	}
+
+	if((*p_ctx->p_callback->eld)->vendor_block_size) {
+		return SS_NOT_SUPPORTED;
+	}
+
+	if((*p_ctx->p_callback->eld)->vendor_ieee_id != CEA_IEEE_HDMI_ID) {
+		return SS_NOT_SUPPORTED;
+	}
+	*/
+	/* Transmitter support is determined by SDVO GetSupportDigitalEncodingModes */
+	status = sdvo_hdmi_transmitter(p_ctx);
+	if (status != SS_SUCCESS) {
+		return status;
+	}
+
+	return SS_SUCCESS;
+}
+
+
+
+/*	============================================================================
+	Function	:	sdvo_hdmi_audio_characteristic
+
+	Parameters	:
+
+	Remarks 	:	Set audio characteristic to be used in ELD calcilation.
+					TODO: Make sure this is recalled if hotplug is detected
+
+	Returns 	:
+	------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_audio_characteristic(sdvo_device_context_t *p_ctx)
+{
+	sdvo_status_t status;
+	i2c_reg_t hdmi_audio_char[3];
+
+	/* Skip since no CEA data available */
+	if((!p_ctx->p_callback) || ((p_ctx->p_callback->eld) == NULL)){
+		return SS_NOT_SUPPORTED;
+	}
+	if(*(p_ctx->p_callback->eld) == NULL){
+		return SS_NOT_SUPPORTED;
+	}
+
+	status = sdvo_get_hdmi_audio_transmission_char(p_ctx, hdmi_audio_char);
+	if(status == SS_SUCCESS){
+		(*p_ctx->p_callback->eld)->audio_flag |= PD_AUDIO_CHAR_AVAIL;
+		(*p_ctx->p_callback->eld)->NPL = hdmi_audio_char[0];
+		(*p_ctx->p_callback->eld)->K0	= hdmi_audio_char[1];
+		(*p_ctx->p_callback->eld)->K1	= hdmi_audio_char[2];
+	}else{
+		(*p_ctx->p_callback->eld)->audio_flag &= ~PD_AUDIO_CHAR_AVAIL;
+	}
+
+	return SS_SUCCESS;
+}
+
+/*	============================================================================
+	Function	:	sdvo_hdmi_configure is called to program AVI infoframes, SPD
+					infoframes, ELD data for audio, colorimetry and pixel replication.
+
+	Parameters	:	p_context: Pointer to port driver allocated context
+								structure
+					p_mode: Point to current video output display mode
+
+	Remarks 	:
+
+	Returns 	:	sdvo_status_t : Status of command execution
+	------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_configure(sdvo_device_context_t *p_ctx)
+{
+	i2c_reg_t data;
+	sdvo_status_t status = SS_SUCCESS;
+	i2c_reg_t encoding_mode = DVI_MODE;
+
+	if((p_ctx->p_callback->eld) == NULL){
+		sdvo_set_digital_encoding_mode(p_ctx, encoding_mode);
+		return SS_NOT_SUPPORTED;
+	}
+	if(*(p_ctx->p_callback->eld) == NULL){
+		sdvo_set_digital_encoding_mode(p_ctx, encoding_mode);
+		return SS_NOT_SUPPORTED;
+	}
+
+	/* Prepare buffer for video information. Video only requires a total of 3
+	 * buffers. (0)ELD (1)AVI (2)SPD. SO we will set it to 2 indexbased buffer */
+	status = sdvo_execute_command(p_ctx, GET_HDMI_BUFFER_AUDIO_VIDEO_SPLIT,
+				0, NULL,
+				1, &data);
+	data = 2;
+	status = sdvo_execute_command(p_ctx, SET_HDMI_BUFFER_AUDIO_VIDEO_SPLIT,
+				1, &data,
+				0, NULL);
+
+	/* Send pixel replication and colorimetry */
+	if (sdvo_hdmi_pr_and_color(p_ctx) != SS_SUCCESS) {
+		PD_ERROR("Fail toset pixel replication and colorimetry");
+	}
+
+	/* Build and send ELD Info Frames */
+	if(sdvo_hdmi_send_eld(p_ctx) != SS_SUCCESS){
+		PD_ERROR("Fail to write ELD to transmitter");
+	}
+
+	/* Build and send AVI Info Frames */
+	if (sdvo_hdmi_avi_info_frame(p_ctx) != SS_SUCCESS) {
+		PD_ERROR("Fail to write AVI infoframes to transmitter");
+	}
+
+	/* Build and send SPD Info Frames */
+#ifndef CONFIG_MICRO
+	if (sdvo_hdmi_spd_info_frame(p_ctx) != SS_SUCCESS) {
+		PD_ERROR("Fail to write SPD Infoframes to transmitter");
+	}
+#endif
+	/* Set to HDMI mode */
+	if((*p_ctx->p_callback->eld)->audio_support){
+		encoding_mode = HDMI_MODE;
+	}
+	status = sdvo_set_digital_encoding_mode(p_ctx, encoding_mode);
+	if (status != SS_SUCCESS) {
+		PD_DEBUG("sdvo: Fail to set HDMI mode ");
+	}
+
+	return SS_SUCCESS;
+}
+/*	============================================================================
+	Function	:	sdvo_hdmi_pr_and_color is called to send pixel replication
+					and colorimetry data to SDVO device.
+
+	Parameters	:	p_context: Pointer to port driver allocated context
+								structure
+
+	Remarks 	:
+
+	Returns 	:	sdvo_status_t : Status of command execution
+	------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_pr_and_color(sdvo_device_context_t *p_context)
+{
+	sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+	sdvo_status_t status = SS_SUCCESS;
+	i2c_reg_t pixel_rep = (i2c_reg_t)(*p_ctx->p_callback->eld)->pixel_rep - 1;
+	i2c_reg_t quantization = (i2c_reg_t)(*p_ctx->p_callback->eld)->quantization;
+
+	/* Set pixel replication */
+	status = sdvo_execute_command(p_ctx, SET_PIXEL_REPLICATION,
+				1, &pixel_rep,
+				0, NULL);
+	if (status != SS_SUCCESS) {
+		return status;
+	}
+
+	/* Set colorimetry */
+	status = sdvo_execute_command(p_ctx, SET_CURRENT_COLORIMETRY,
+				1, &quantization,
+				0, NULL);
+	if (status != SS_SUCCESS) {
+		return status;
+	}
+	return status;
+};
+/*	============================================================================
+	Function	:	sdvo_hdmi_send_eld
+
+	Parameters	:
+
+	Remarks 	:	Builds eld structure and write it into SDVO ELD buffers
+
+	Returns 	:
+	------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_send_eld(sdvo_device_context_t *p_ctx)
+{
+	sdvo_status_t status;
+	sdvo_audio_state_t audio_state;
+
+	if((p_ctx->p_callback->eld) == NULL){
+		return SS_NOT_SUPPORTED;
+	}
+	if(*(p_ctx->p_callback->eld) == NULL){
+		return SS_NOT_SUPPORTED;
+	}
+	if(!((*p_ctx->p_callback->eld)->audio_flag & ELD_AVAIL)){
+		PD_DEBUG("Eld not available");
+		return SS_NOT_SUPPORTED;
+	}
+
+	/* ELD 1.0, CEA version retrieve from callback */
+	(*p_ctx->p_callback->eld)->cea_ver = 0;
+	(*p_ctx->p_callback->eld)->eld_ver = 1;
+
+	/* Capability Flags */
+	(*p_ctx->p_callback->eld)->repeater = 0;
+	(*p_ctx->p_callback->eld)->hdcp = 0;
+#ifdef CONFIG_MICRO
+	(*p_ctx->p_callback->eld)->_44ms = 0;
+#endif
+
+	/* We do not provide Monitor length */
+	(*p_ctx->p_callback->eld)->mnl = 0;
+
+#ifdef CONFIG_MICRO
+	(*p_ctx->p_callback->eld)->sadc = 0;
+#endif
+
+	audio_state.value = 0;
+	audio_state.eld_valid = FALSE;
+	audio_state.presense_detect = TRUE;
+	status = sdvo_execute_command(p_ctx, SET_AUDIO_STATE,
+				1, (i2c_reg_t *)&audio_state,
+				0, NULL);
+	if (status != SS_SUCCESS) {
+		PD_ERROR("Set Audio eld_valid  fail (FALSE)");
+		return status;
+	}
+
+	/* Write ELD to SDVO buffers */
+	status = sdvo_hdmi_write_buffer(p_ctx, SDVO_HDMI_ELD_BUFFER ,
+		0,  (*p_ctx->p_callback->eld)->eld_ptr, SDVO_HDMI_ELD_BUFFER_SIZE);
+	if (status != SS_SUCCESS) {
+		PD_ERROR("Write ELD Failed !");
+		return status;
+	}
+
+	/* Send audio state change by toggling eld_valid bit */
+	audio_state.eld_valid = TRUE;
+	status = sdvo_execute_command(p_ctx, SET_AUDIO_STATE,
+				1, (i2c_reg_t *)&audio_state,
+				0, NULL);
+	if (status != SS_SUCCESS) {
+		PD_ERROR("Set Audio eld_valid  fail (TRUE)");
+		return status;
+	}
+
+	return SS_SUCCESS;
+}
+/*	============================================================================
+	Function	:	sdvo_hdmi_avi_info_frame is called to program AVI infoframes
+
+	Parameters	:	p_context: Pointer to port driver allocated context
+								structure
+					p_mode: Point to current video output display mode
+
+	Remarks 	:
+
+	Returns 	:	sdvo_status_t : Status of command execution
+	------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_avi_info_frame(sdvo_device_context_t *p_context)
+{
+	sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+	sdvo_status_t status = SS_SUCCESS;
+	unsigned long sum = 0;
+	int i;
+	sdvo_avi_info_t		avi;
+
+	/* Initialize AVI InfoFrame to no scan info, no bar info, no active format */
+	/* mode rgb, active format same as picture format */
+	/* no aspect ratio, no colorimetry, no scaling */
+	pd_memset(&avi, 0, sizeof(sdvo_avi_info_t));
+	avi.header.type = SDVO_HDMI_AVI_INFO_TYPE;
+	avi.header.version = 2;
+	avi.header.length = SDVO_HDMI_AVI_BUFFER_SIZE - sizeof(sdvo_info_header_t);
+
+	/* Fill in VIC, colorimetry, aspect ratio */
+
+	/* Set Video ID Code */
+	avi.video_id_code = (unsigned char)(*p_ctx->p_callback->eld)->video_code;
+
+	/* Set aspect ratio */
+	avi.pic_aspect_ratio = (unsigned char)(*p_ctx->p_callback->eld)->aspect_ratio;
+
+	/* Set Colorimetry */
+	avi.colorimetry = (unsigned char)(*p_ctx->p_callback->eld)->colorimetry;
+
+	/* Calc checksum */
+	for (i= 0; i < SDVO_HDMI_AVI_BUFFER_SIZE; i++) {
+		sum += avi.data[i];
+	}
+	avi.header.chksum = (unsigned char)(0x100 - (sum & 0xFF));
+
+	/* Send data to SDVO device */
+	status = sdvo_hdmi_write_buffer(p_ctx, SDVO_HDMI_AVI_BUFFER, 0, avi.data,
+		SDVO_HDMI_AVI_BUFFER_SIZE);
+	return status;
+};
+/*	============================================================================
+	Function	:	sdvo_hdmi_spd_info_frame is called to program SPD infoframes
+
+	Parameters	:	p_context: Pointer to port driver allocated context
+								structure
+
+	Remarks 	:
+
+	Returns 	:	sdvo_status_t : Status of command execution
+	------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_spd_info_frame(sdvo_device_context_t *p_context)
+{
+	sdvo_device_context_t *p_ctx = (sdvo_device_context_t *)p_context;
+	sdvo_status_t status = SS_SUCCESS;
+	sdvo_spd_info_t		spd;
+	unsigned long sum = 0;
+	int i;
+
+	/* Initialize SPD InfoFrame to zero */
+	pd_memset(&spd, 0, sizeof(sdvo_spd_info_t));
+	spd.header.type = SDVO_HDMI_SPD_INFO_TYPE;
+	spd.header.version = 1;
+	spd.header.length = SDVO_HDMI_SPD_BUFFER_SIZE - sizeof(sdvo_info_header_t);
+
+	pd_memcpy(spd.vendor_name, SDVO_HDMI_VENDOR_NAME, SDVO_HDMI_INTEL_VENDOR_NAME_SIZE);
+	pd_memcpy(spd.product_desc,
+		SDVO_HDMI_VENDOR_DESCRIPTION, SDVO_HDMI_IEGD_VENDOR_DESCRIPTION_SIZE);
+	spd.source_device = SDVO_HDMI_SPD_SOURCE_PC;
+
+	/* Calc checksum */
+	for (i= 0; i < SDVO_HDMI_SPD_BUFFER_SIZE; i++) {
+		sum += spd.data[i];
+	}
+	spd.header.chksum = (unsigned char)(0x100 - (sum & 0xFF));
+
+	/* Send data to SDVO device */
+	status = sdvo_hdmi_write_buffer
+		(p_ctx, SDVO_HDMI_SPD_BUFFER, 0, spd.data, SDVO_HDMI_SPD_BUFFER_SIZE);
+	return status;
+};
+/*	============================================================================
+	Function	:	sdvo_hdmi_write_buffer
+
+	Parameters	:
+
+	Remarks 	:	Write into SDVO buffers
+
+	Returns 	:
+	------------------------------------------------------------------------- */
+sdvo_status_t sdvo_hdmi_write_buffer
+	(sdvo_device_context_t *p_ctx,unsigned char index,
+	unsigned char offset, unsigned char *input, int len)
+{
+	sdvo_status_t status;
+	i2c_reg_t hdmi_index[2],data[8];
+	int buffer_size = 0;
+	unsigned char total_bytes, *p_sdvo_buffer, *ori_p_sdvo_buffer;
+
+	/* Set Buffer index and offset */
+	hdmi_index[0] = index;
+	hdmi_index[1] = offset;
+	status = sdvo_execute_command(p_ctx, SET_HDMI_BUFFER_INDEX,
+				2, hdmi_index,
+				0, NULL);
+	if (status != SS_SUCCESS) {
+		PD_ERROR("HDMI wirte buffer fail : Set index");
+		return status;
+	}
+
+	/* Setup buffer transmit rate */
+	if(index != SDVO_HDMI_ELD_BUFFER){
+		data[0] = SDVO_HDMI_TRANSMIT_EVERY;
+		status = sdvo_execute_command(p_ctx, SET_HDMI_BUFFER_TRANSMIT_RATE,
+					1, data,
+					0, NULL);
+		if (status != SS_SUCCESS) {
+			PD_ERROR("HDMI wirte buffer fail : Transmite rate");
+			return status;
+		}
+	}
+	else {
+		status = sdvo_execute_command(p_ctx, GET_HDMI_BUFFER_TRANSMIT_RATE,
+					0, NULL,
+					1, data);
+		if (status != SS_SUCCESS) {
+			PD_ERROR("HDMI wirte buffer fail : Transmite rate");
+			return status;
+		}
+	}
+
+	/* Get buffer size info */
+	status = sdvo_execute_command(p_ctx, GET_HDMI_BUFFER_INFO,
+			0, NULL,
+			1, (i2c_reg_t *)&data);
+	buffer_size = data[0] + 1;
+	/* Minimum buffer size is 3 then something is wrong */
+	if (status != SS_SUCCESS || buffer_size <0x03) {
+		PD_ERROR("HDMI wirte buffer fail : Buffer size");
+		return status;
+	}
+
+	/* Make sure to query size of buffer from SDVO and use it, not size of source infoframe buffers */
+	/* copy structs into cleared memory the size of SDVO buffer */
+	p_sdvo_buffer = pd_malloc(buffer_size);
+	ori_p_sdvo_buffer = p_sdvo_buffer;
+	pd_memset(p_sdvo_buffer, 0, buffer_size);
+	pd_memcpy(p_sdvo_buffer, input, (len < buffer_size) ? len : buffer_size);
+
+	while(buffer_size) {
+		//total_bytes = (buffer_size >= 8) ? 8:buffer_size;
+		if(buffer_size >= 8)	total_bytes = 8;
+		else					total_bytes = (unsigned char)buffer_size;
+
+		status = sdvo_execute_command(p_ctx, SET_HDMI_BUFFER_DATA,
+				total_bytes, (i2c_reg_t *)p_sdvo_buffer,
+				0, NULL);
+		if (status != SS_SUCCESS) {
+			PD_ERROR("HDMI wirte buffer fail : Set buffer data");
+			return status;
+		}
+		p_sdvo_buffer +=total_bytes;
+		buffer_size -= total_bytes;
+	};
+
+	pd_free(ori_p_sdvo_buffer);
+	return SS_SUCCESS;
+}
+
+#endif/* SDVO_HDMI */
+
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.h b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.h
new file mode 100644
index 0000000..64c06c1
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_hdmi.h
@@ -0,0 +1,182 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sdvo_hdmi.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Main include file for SDVO port driver HDMI interface function
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _SDVO_PORT_HDMI_H_
+#define _SDVO_PORT_HDMI_H_
+
+#include <config.h>
+#include <igd_pd.h>
+#include <pd.h>
+#include <pd_print.h>
+#include "sdvo_port.h"
+#include "sdvo_intf.h"
+
+/* VBios abstraction macro */
+#if !defined(CONFIG_MICRO)
+#define SDVO_HDMI
+#endif
+
+
+#if defined(SDVO_HDMI)
+
+#define SDVO_HDMI_ELD_BUFFER_SIZE			256
+#define SDVO_HDMI_AVI_BUFFER_SIZE			17
+#define SDVO_HDMI_SPD_BUFFER_SIZE			29
+#define	SDVO_HDMI_ELD_BUFFER				0			/* ELD buffer index */
+#define SDVO_HDMI_AVI_BUFFER				1			/* AVI buffer index */
+#define SDVO_HDMI_SPD_BUFFER				2			/* SPD buffer index */
+#define SDVO_HDMI_ELD_INFO_TYPE				0x00		/* ELD buffer type */
+#define SDVO_HDMI_AVI_INFO_TYPE				0x82		/* AVI buffer type */
+#define SDVO_HDMI_SPD_INFO_TYPE				0x83		/* SPD buffer type */
+#define SDVO_HDMI_AVI_BUFFER_SIZE			17
+#define SDVO_HDMI_TRANSMIT_DISABLE			0x00
+#define SDVO_HDMI_TRANSMIT_ONCE				0x80
+#define SDVO_HDMI_TRANSMIT_EVERY			0xC0
+
+#define SDVO_HDMI_VENDOR_NAME				"Intel"
+#define SDVO_HDMI_VENDOR_DESCRIPTION		"IEGD Driver"
+#define SDVO_HDMI_INTEL_VENDOR_NAME_SIZE		6
+#define SDVO_HDMI_IEGD_VENDOR_DESCRIPTION_SIZE	12
+
+#define SDVO_HDMI_VENDOR_NAME_SIZE			8
+#define SDVO_HDMI_VENDOR_DESCRIPTION_SIZE	16
+#define SDVO_HDMI_SPD_SOURCE_PC				0x09
+
+#define DVI_MODE	0
+#define HDMI_MODE	1
+sdvo_status_t sdvo_hdmi_transmitter(sdvo_device_context_t *p_context);
+sdvo_status_t sdvo_hdmi_support(void *p_context);
+sdvo_status_t sdvo_hdmi_audio_characteristic(sdvo_device_context_t *p_context);
+sdvo_status_t sdvo_hdmi_configure(sdvo_device_context_t *p_ctx);
+sdvo_status_t sdvo_hdmi_pr_and_color(sdvo_device_context_t *p_context);
+sdvo_status_t sdvo_hdmi_send_eld(sdvo_device_context_t *p_ctx);
+sdvo_status_t sdvo_hdmi_avi_info_frame(sdvo_device_context_t *p_context);
+sdvo_status_t sdvo_hdmi_spd_info_frame(sdvo_device_context_t *p_context);
+sdvo_status_t sdvo_hdmi_write_buffer
+	(sdvo_device_context_t *p_ctx,unsigned char index,
+	unsigned char offset, unsigned char *input, int len);
+
+typedef union
+{
+	unsigned char value;
+	struct {
+		unsigned char eld_valid: 1;
+		unsigned char presense_detect: 1;
+		unsigned char cp_ready: 1;
+		unsigned char reserved: 5;
+	};
+} sdvo_audio_state_t;
+/* AVI Info Frames version 2 */
+typedef struct
+{
+	unsigned char type;
+	unsigned char version;
+	unsigned char length;
+	unsigned char chksum;
+} sdvo_info_header_t;
+
+typedef union
+{
+	unsigned char data[SDVO_HDMI_AVI_BUFFER_SIZE];
+	struct {
+		sdvo_info_header_t	header;
+		union {
+			unsigned char data1;
+			struct {
+				unsigned char scan_info: 2;
+				unsigned char bar_info: 2;
+				unsigned char active_format: 1;
+				unsigned char color_space: 2;
+				unsigned char reserved1: 1;
+			};
+		};
+		union {
+			unsigned char data2;
+			struct {
+				unsigned char format_aspect_ratio: 4;
+				unsigned char pic_aspect_ratio: 2;
+				unsigned char colorimetry: 2;
+			};
+		};
+		union {
+			unsigned char data3;
+			struct {
+				unsigned char pic_scaling: 2;
+				unsigned char reserved2: 6;
+			};
+		};
+		union {
+			unsigned char data4;
+			struct {
+				unsigned char video_id_code: 7;
+				unsigned char reserved3: 1;
+			};
+		};
+		union {
+			unsigned char data5;
+			struct {
+				unsigned char pixel_rep: 4;
+				unsigned char reserved4: 4;
+			};
+		};
+		unsigned char bar1;
+		unsigned char bar2;
+		unsigned char bar3;
+		unsigned char bar4;
+		unsigned char bar5;
+		unsigned char bar6;
+		unsigned char bar7;
+		unsigned char bar8;
+	};
+} sdvo_avi_info_t;
+
+typedef union
+{
+	unsigned char data[SDVO_HDMI_SPD_BUFFER_SIZE];
+	struct {
+		sdvo_info_header_t	header;
+		unsigned char vendor_name[SDVO_HDMI_VENDOR_NAME_SIZE];
+		unsigned char product_desc[SDVO_HDMI_VENDOR_DESCRIPTION_SIZE];
+		unsigned char source_device;
+	};
+} sdvo_spd_info_t;
+
+
+#define SDVO_INIT_HDMI(a)			sdvo_hdmi_audio_characteristic(a)
+#define SDVO_IS_HDMI_SUPPORTED(a)	sdvo_hdmi_support(a)
+#define SDVO_CONFIGURE_HDMI(a)		sdvo_hdmi_configure(a)
+#else
+#define SDVO_INIT_HDMI(a)
+#define SDVO_IS_HDMI_SUPPORTED(a)		SS_NOT_SUPPORTED
+#define SDVO_CONFIGURE_HDMI(a)
+#endif  /* SDVO_HDMI */
+
+#endif  /*  _SDVO_PORT_HDMI_H_ */
diff --git a/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.c b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.c
new file mode 100644
index 0000000..e2fb741
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.c
@@ -0,0 +1,725 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sdvo_intf.c
+ * $Revision: 1.12 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Functions that provide interface to SDVO device
+ *-----------------------------------------------------------------------------
+ */
+
+#include "sdvo_port.h"
+
+/* .......................................................................... */
+void sdvo_convert_parm_to_dtd(i2c_reg_t parm[16], sdvo_dtd_t *p_dtd);
+void sdvo_convert_dtd_to_parm(
+	sdvo_device_context_t *p_ctx,
+	sdvo_dtd_t *p_dtd,
+	i2c_reg_t parm[16]);
+
+
+/* .......................................................................... */
+/* .......................................................................... */
+/*	============================================================================
+	Function	:	sdvo_execute_command transfers a command and argument to
+					the SDVO device and returns the status of execution
+
+	Parameters	:	opcode		: One of the sdvo_opcode_t opcodes
+					num_args 	: Number of arguments 0-8
+					p_arg	    : List of arguments
+					num_returns	: Expected number of returns 0-8
+					p_ret_value	: List of return values
+
+	Remarks 	:	sdvo_execute_command is core function that is called by other
+					SDVO interface functions to execute a command.
+					The arguments of the command are transferred to the argument
+					I2C registers of the SDVO device
+					The opcode is then transferred to the opcode I2C register
+					It then waits for the command to complete by reading the
+					status I2C register up to 3 times
+
+	Returns 	:	sdvo_status_t : Status of command execution
+	------------------------------------------------------------------------- */
+sdvo_status_t sdvo_execute_command(sdvo_device_context_t *p_ctx,
+	sdvo_opcode_t opcode,
+	i2c_reg_t num_args,	   i2c_reg_t *p_arg,
+	i2c_reg_t num_returns, i2c_reg_t *p_ret_value)
+{
+	i2c_reg_t status, i;
+
+	/*	..................................................................... */
+	/*	Error checking */
+	if ((num_args > SDVO_MAX_ARGS) || (num_returns > SDVO_MAX_RETURNS)) {
+
+		return SS_UNSUCCESSFUL;
+	}
+
+	if ((num_args > 0) && (p_arg == NULL)) {
+
+		return SS_UNSUCCESSFUL;
+	}
+
+	if ((num_returns > 0) && (p_ret_value == NULL)) {
+
+		return SS_UNSUCCESSFUL;
+	}
+
+	/*	..................................................................... */
+	/*	Write the arguments and the opcode */
+	for (i = 0; i < num_args; i++) {
+
+		if (! sdvo_write_i2c_reg(p_ctx, (i2c_reg_t)(SDVO_REG_ARG_START - i),
+				p_arg[i])) {
+
+			return SS_WRITE_FAILED;
+		}
+	}
+
+	if (! sdvo_write_i2c_reg(p_ctx, (i2c_reg_t)SDVO_REG_OPCODE,
+			(i2c_reg_t)opcode)) {
+
+		return SS_WRITE_FAILED;
+	}
+
+	/*	..................................................................... */
+	/*	Wait for command to complete */
+	for (i = 0; i < SDVO_MAX_RETRIES; i++) {
+
+		if (! sdvo_read_i2c_reg(p_ctx, SDVO_REG_STATUS, &status)) {
+
+			return SS_READ_FAILED;
+		}
+
+		if (status != SS_PENDING) {
+
+			break;
+		}
+	}
+
+	/*	..................................................................... */
+	/*	Read the return parameters if command succeeded */
+	if (status == SS_SUCCESS) {
+
+		for (i = 0; i < num_returns; i++) {
+
+			if (! sdvo_read_i2c_reg(p_ctx, SDVO_REG_RETURN_START + i,
+					&p_ret_value[i])) {
+
+				 return SS_READ_FAILED;
+			}
+		}
+	}
+
+	return status;
+}
+
+sdvo_status_t sdvo_execute_command_read (sdvo_device_context_t *p_ctx,
+	i2c_reg_t num_returns, i2c_reg_t *p_ret_value)
+{
+	i2c_reg_t status, i;
+
+	for (i = 0; i < SDVO_MAX_RETRIES; i++) {
+		if (!sdvo_read_i2c_reg(p_ctx, SDVO_REG_STATUS, &status)) {
+			return SS_READ_FAILED;
+		}
+
+		if (status != SS_PENDING) {
+			break;
+		}
+	}
+
+	/*	Read the return parameters if command succeeded */
+	if (status == SS_SUCCESS) {
+		for (i = 0; i < num_returns; i++) {
+			if (! sdvo_read_i2c_reg(p_ctx, SDVO_REG_RETURN_START + i,
+					&p_ret_value[i])) {
+				 return SS_READ_FAILED;
+			}
+		}
+	}
+	return status;
+}
+
+#ifndef CONFIG_MICRO
+sdvo_status_t sdvo_reset(sdvo_device_context_t *p_ctx)
+{
+	return sdvo_execute_command(p_ctx, RESET,
+							   0, NULL,
+							   0, NULL);
+}
+#endif
+
+sdvo_status_t sdvo_get_device_capabilities(sdvo_device_context_t *p_ctx,
+	sdvo_device_capabilities_t *p_Dev_Cap)
+{
+	return sdvo_execute_command(p_ctx, GET_DEVICE_CAPABILITIES,
+							    0, NULL,
+							    8, (i2c_reg_t *)p_Dev_Cap);
+}
+
+
+sdvo_status_t sdvo_get_trained_inputs(sdvo_device_context_t *p_ctx,
+	i2c_reg_t *p_Out)
+{
+	return sdvo_execute_command(p_ctx, GET_TRAINED_INPUTS,
+							   0, NULL,
+							   1, p_Out);
+}
+
+
+sdvo_status_t sdvo_get_active_outputs(sdvo_device_context_t *p_ctx,
+	sdvo_output_flags_t *p_Out_Flags)
+{
+	return sdvo_execute_command(p_ctx, GET_ACTIVE_OUTPUTS,
+				0, NULL,
+				2, (i2c_reg_t *)p_Out_Flags);
+}
+
+
+sdvo_status_t sdvo_set_active_outputs(sdvo_device_context_t *p_ctx,
+	sdvo_output_flags_t out_flags)
+{
+	return sdvo_execute_command(p_ctx, SET_ACTIVE_OUTPUTS,
+			   2, (i2c_reg_t *)&out_flags,
+			   0, NULL);
+}
+
+
+#ifndef CONFIG_MICRO
+sdvo_status_t sdvo_get_in_out_map(sdvo_device_context_t *p_ctx,
+	sdvo_output_flags_t out_flags[2])
+{
+	return sdvo_execute_command(p_ctx, GET_IN_OUT_MAP,
+				0, NULL,
+				4, (i2c_reg_t *)out_flags);
+}
+#endif
+
+sdvo_status_t sdvo_set_in_out_map(sdvo_device_context_t *p_ctx,
+	sdvo_output_flags_t out_flags[2])
+{
+	return sdvo_execute_command(p_ctx, SET_IN_OUT_MAP,
+				4, (i2c_reg_t *)out_flags,
+				0, NULL);
+}
+
+
+sdvo_status_t sdvo_get_attached_displays(sdvo_device_context_t *p_ctx,
+	sdvo_output_flags_t *p_Out_Flags)
+{
+	i2c_reg_t status, i;
+
+	status = sdvo_execute_command(p_ctx, GET_ATTACHED_DISPLAYS,
+				0, NULL,
+				2, (i2c_reg_t *)p_Out_Flags);
+
+
+	PD_DEBUG("sdvo: GET_ATTACHED_DISPLAYS status = %d]",  status);
+	for (i=0; i<5; i++) {
+		if (status == SS_SUCCESS)
+			break;
+		else {
+			pd_ui_usleep(50000); /* wait for 50ms */
+			status = sdvo_execute_command_read(p_ctx, 2, (i2c_reg_t *)p_Out_Flags);
+		}
+	}
+
+	PD_DEBUG("sdvo: sdvo_execute_command_read- no. of tries = [%d]",  i);
+	return status;
+}
+
+
+sdvo_status_t sdvo_set_target_input(sdvo_device_context_t *p_ctx,
+	sdvo_target_input_t input)
+{
+	i2c_reg_t arg_value = input == SDVO0 ? 0 : 1;
+
+	return sdvo_execute_command(p_ctx, SET_TARGET_INPUT,
+				1, (i2c_reg_t *)&arg_value,
+				0, NULL);
+}
+
+
+sdvo_status_t sdvo_set_target_output(sdvo_device_context_t *p_ctx,
+		sdvo_output_flags_t out_flags)
+{
+	return sdvo_execute_command(p_ctx, SET_TARGET_OUTUT,
+			   2, (i2c_reg_t *)&out_flags,
+			   0, NULL);
+}
+
+#ifndef CONFIG_MICRO
+sdvo_status_t sdvo_get_input_timings(sdvo_device_context_t *p_ctx,
+								 sdvo_dtd_t *p_dtd)
+{
+	sdvo_status_t status;
+	i2c_reg_t ret[16];
+
+	status = sdvo_execute_command(p_ctx, GET_INPUT_TIMINGS_PART1,
+				0, NULL,
+				8, ret);
+	if (status != SS_SUCCESS) {
+
+		return status;
+	}
+
+	status = sdvo_execute_command(p_ctx, GET_INPUT_TIMINGS_PART2,
+				 0, NULL,
+				 8, &ret[8]);
+	if (status != SS_SUCCESS) {
+
+		return status;
+	}
+
+	sdvo_convert_parm_to_dtd(ret, p_dtd);
+
+	return status;
+}
+#endif
+
+sdvo_status_t sdvo_set_input_timings(sdvo_device_context_t *p_ctx,
+								 sdvo_dtd_t *p_dtd)
+{
+	sdvo_status_t status;
+	i2c_reg_t parm[16];
+
+	sdvo_convert_dtd_to_parm(p_ctx, p_dtd, parm);
+
+	status = sdvo_execute_command(p_ctx, SET_INPUT_TIMINGS_PART1,
+				 8, parm,
+				 0, NULL);
+
+	if ((status != SS_SUCCESS) && (status != SS_NOT_SUPPORTED)) {
+
+		return status;
+	}
+
+	status = sdvo_execute_command(p_ctx, SET_INPUT_TIMINGS_PART2,
+				 8, &parm[8],
+				 0, NULL);
+
+	return status;
+}
+
+#ifndef CONFIG_MICRO
+sdvo_status_t sdvo_get_output_timings(sdvo_device_context_t *p_ctx,
+	sdvo_dtd_t *p_dtd)
+{
+	sdvo_status_t status;
+	i2c_reg_t ret[16];
+
+	status = sdvo_execute_command(p_ctx, GET_OUTPUT_TIMINGS_PART1,
+				 0, NULL,
+				 8, ret);
+	if ((status != SS_SUCCESS) && (status != SS_NOT_SUPPORTED)) {
+
+		return status;
+	}
+
+	status = sdvo_execute_command(p_ctx, GET_OUTPUT_TIMINGS_PART2,
+				 0, NULL,
+				 8, &ret[8]);
+	if (status != SS_SUCCESS) {
+
+		return status;
+	}
+
+	sdvo_convert_parm_to_dtd(ret, p_dtd);
+
+	return status;
+}
+#endif
+
+sdvo_status_t sdvo_set_output_timings(sdvo_device_context_t *p_ctx,
+  sdvo_dtd_t *p_dtd)
+{
+	sdvo_status_t status;
+	i2c_reg_t parm[16];
+
+	sdvo_convert_dtd_to_parm(p_ctx, p_dtd, parm);
+
+	status = sdvo_execute_command(p_ctx, SET_OUTPUT_TIMINGS_PART1,
+				 8, parm,
+				 0, NULL);
+
+	if (status != SS_SUCCESS) {
+
+		return status;
+	}
+
+	status = sdvo_execute_command(p_ctx, SET_OUTPUT_TIMINGS_PART2,
+				 8, &parm[8],
+				 0, NULL);
+
+	return status;
+}
+
+
+sdvo_status_t sdvo_get_preferred_input_timings(sdvo_device_context_t *p_ctx,
+				  sdvo_create_preferred_timings_t *p_Timings,
+				  sdvo_dtd_t *p_dtd)
+{
+	sdvo_status_t status;
+	i2c_reg_t ret[16];
+
+	/*	..................................................................... */
+	status = sdvo_execute_command(p_ctx, CREATE_PREFERRED_INPUT_TIMINGS,
+				 7, (i2c_reg_t *)p_Timings,
+				 0, NULL);
+	if (status != SS_SUCCESS) {
+
+		return status;
+	}
+
+	/*	..................................................................... */
+	status =  sdvo_execute_command(p_ctx, GET_PREFERRED_INPUT_TIMINGS_PART1,
+				  0, NULL,
+				  8, ret);
+	if (status != SS_SUCCESS) {
+
+		return status;
+	}
+
+	status = sdvo_execute_command(p_ctx, GET_PREFERRED_INPUT_TIMINGS_PART2,
+				 0, NULL,
+				 8, &ret[8]);
+	if (status != SS_SUCCESS) {
+
+		return status;
+	}
+
+	/*	..................................................................... */
+	sdvo_convert_parm_to_dtd(ret, p_dtd);
+
+	return status;
+}
+
+
+/*	in_clock[0] = min, in_clock[1] = max */
+sdvo_status_t sdvo_get_input_pixel_clock_range(sdvo_device_context_t *p_ctx,
+	unsigned short in_clock[2])
+{
+	return sdvo_execute_command(p_ctx, GET_INPUT_PIXEL_CLOCK_RANGE,
+			   0, NULL,
+			   4, (i2c_reg_t *)in_clock);
+}
+
+#ifndef CONFIG_MICRO
+/*	out_Clock[0] = min, out_Clock[1] = max */
+sdvo_status_t sdvo_get_output_pixel_clock_range(sdvo_device_context_t *p_ctx,
+				  unsigned short out_Clock[2])
+{
+	return sdvo_execute_command(p_ctx, GET_OUTPUT_PIXEL_CLOCK_RANGE,
+			   0, NULL,
+			   4, (i2c_reg_t *)out_Clock);
+}
+
+sdvo_status_t sdvo_get_clock_rate_multiplier(sdvo_device_context_t *p_ctx,
+	sdvo_clock_rate_mult_t *p_mult)
+{
+	*p_mult = 0;
+
+	return sdvo_execute_command(p_ctx, GET_SDVO_CLOCK_RATE_MULTIPLIER,
+			   0, NULL,
+			   1, (i2c_reg_t *)p_mult);
+}
+#endif
+
+
+sdvo_status_t sdvo_set_clock_rate_multiplier(sdvo_device_context_t *p_ctx,
+	sdvo_clock_rate_mult_t mult)
+{
+	return sdvo_execute_command(p_ctx, SET_SDVO_CLOCK_RATE_MULTIPLIER,
+			   1, (i2c_reg_t *)&mult,
+			   0, NULL);
+}
+
+
+sdvo_status_t sdvo_get_supported_power_states(sdvo_device_context_t *p_ctx,
+	 i2c_reg_t *p_pwr_state)
+{
+	return sdvo_execute_command(p_ctx, GET_SUPPORTED_POWER_STATES,
+			   0, NULL,
+			   1, p_pwr_state);
+}
+
+
+sdvo_status_t sdvo_get_power_state(sdvo_device_context_t *p_ctx,
+	   i2c_reg_t *p_pwr_state)
+{
+	return sdvo_execute_command(p_ctx, GET_POWER_STATE,
+			   0, NULL,
+			   1, p_pwr_state);
+}
+
+
+sdvo_status_t sdvo_set_power_state(sdvo_device_context_t *p_ctx,
+   i2c_reg_t pwr_state)
+{
+	return sdvo_execute_command(p_ctx, SET_POWER_STATE,
+			   1, &pwr_state,
+			   0, NULL);
+}
+
+
+sdvo_status_t sdvo_set_display_power_state(sdvo_device_context_t *p_ctx,
+  i2c_reg_t disp_pwr_state)
+{
+	return sdvo_execute_command(p_ctx, SET_DISPLAY_POWER_STATE,
+			   1, &disp_pwr_state,
+			   0, NULL);
+}
+#if !defined(CONFIG_MICRO)
+sdvo_status_t sdvo_set_digital_encoding_mode(sdvo_device_context_t *p_ctx,
+  i2c_reg_t digital_encoding_mode)
+{
+	return sdvo_execute_command(p_ctx, SET_DIGITAL_ENCODING_MODE,
+			   1, &digital_encoding_mode,
+			   0, NULL);
+}
+sdvo_status_t sdvo_get_hdmi_audio_transmission_char(sdvo_device_context_t *p_ctx,
+  i2c_reg_t *hdmi_reg)
+{
+	return sdvo_execute_command(p_ctx, GET_HDMI_AUDIO_TRANSMISSION_CHARACTERISTICS,
+			   0, NULL,
+			   3, (i2c_reg_t*)hdmi_reg);
+}
+sdvo_status_t sdvo_get_supported_encoding_modes(sdvo_device_context_t *p_ctx,
+  sdvo_digital_encode_modes_t *digital_encoding_modes)
+{
+	return sdvo_execute_command(p_ctx, GET_SUPPORTED_DIGITAL_ENCODING_MODES,
+			   0, NULL,
+			   8, (i2c_reg_t*)digital_encoding_modes);
+}
+
+sdvo_status_t sdvo_get_digital_encoding_mode(sdvo_device_context_t *p_ctx,
+  i2c_reg_t *digital_encoding_mode)
+{
+	return sdvo_execute_command(p_ctx, GET_DIGITAL_ENCODING_MODE,
+			   0, NULL,
+			   1, (i2c_reg_t*)digital_encoding_mode);
+}
+/* ------------------------------------------------------------------------- */
+#endif
+sdvo_status_t sdvo_set_upscalar_coefficient(sdvo_device_context_t *p_ctx,
+  i2c_reg_t upscalar_coefficient)
+{
+	return sdvo_execute_command(p_ctx, SET_UPSCALAR_COEFFICIENTS,
+			   1, &upscalar_coefficient,
+			   0, NULL);
+}
+
+sdvo_status_t sdvo_get_tv_output_format(sdvo_device_context_t *p_ctx,
+	i2c_reg_t *p_TV_Output_Format_Flag)
+{
+	return sdvo_execute_command(p_ctx, GET_TV_OUTPUT_FORMAT,
+				0, NULL,
+				6, p_TV_Output_Format_Flag);
+}
+
+sdvo_status_t sdvo_get_sdtv_resolution_support(sdvo_device_context_t *p_ctx,
+	i2c_reg_t *p_Requested_SDTV_Format_Flag,
+	i2c_reg_t *p_Resolution_Support_Flags)
+{
+	return sdvo_execute_command(p_ctx, GET_SDTV_RESOLUTION_SUPPORT,
+				3, p_Requested_SDTV_Format_Flag,
+				3, p_Resolution_Support_Flags);
+}
+
+sdvo_status_t sdvo_get_scaled_hdtv_resolution_support(sdvo_device_context_t *p_ctx,
+	i2c_reg_t *p_Requested_HDTV_Format_Flag,
+	i2c_reg_t *p_Resolution_Support_Flags)
+{
+	return sdvo_execute_command(p_ctx, GET_SCALED_HDTV_RESOLUTION_SUPPORT,
+				4, p_Requested_HDTV_Format_Flag,
+				8, p_Resolution_Support_Flags);
+}
+
+void sdvo_convert_parm_to_dtd(i2c_reg_t parm[16], sdvo_dtd_t *p_dtd)
+{
+	pd_memset(p_dtd, 0, sizeof(sdvo_dtd_t));
+
+	p_dtd->pixel_clock			= (parm[1] << 8) | parm[0];
+	p_dtd->horz_active			= ((parm[4] & 0xF0) << 4) | parm[2];
+	p_dtd->horz_blanking		= ((parm[4] & 0x0F) << 8) | parm[3];
+	p_dtd->vert_active			= ((parm[7] & 0xF0) << 4) | parm[5];
+	p_dtd->vert_blanking		= ((parm[7] & 0x0F) << 8) | parm[6];
+	p_dtd->horz_sync_offset		= ((parm[11] & 0xC0) << 2) | parm[8];
+	p_dtd->horz_sync_pulse_width= ((parm[11] & 0x30) << 4) | parm[9];
+	p_dtd->vert_sync_offset		= (parm[14] & 0xC0) | ((parm[11] & 0x0C) << 2) |
+								  ((parm[10] & 0xF0) >> 4);
+	p_dtd->vert_sync_pulse_width= ((parm[11] & 0x03) << 4) | (parm[10] & 0x0F);
+	p_dtd->dtd_flags			= parm[12];
+	p_dtd->sdvo_flags			= parm[13];
+}
+
+
+void sdvo_convert_dtd_to_parm(
+	sdvo_device_context_t *p_ctx,
+	sdvo_dtd_t *p_dtd,
+	i2c_reg_t parm[16])
+{
+	unsigned int multp;
+
+	parm[0]  = (p_dtd->pixel_clock & 0xFF);
+	parm[1]  = ((p_dtd->pixel_clock & 0xFF00) >> 8);
+
+	if (p_ctx->st_sdvo) {
+		if (p_dtd->pixel_clock > 10000) {			/*	100-200 MHz */
+			multp = 1;
+		} else if (p_dtd->pixel_clock > 5000) {     /*	50-100 Mhz */
+			multp = 2;
+		} else {							        /*	25-50 Mhz */
+			multp = 4;
+		}
+
+		parm[2]  = ((p_dtd->horz_active * multp) & 0xFF);
+		parm[3]  = ((p_dtd->horz_blanking * multp) & 0xFF);
+		parm[4]  = ((((p_dtd->horz_active * multp) & 0xF00) >> 4) |
+					(((p_dtd->horz_blanking * multp) & 0xF00) >> 8));
+	} else {
+		parm[2]  = (p_dtd->horz_active & 0xFF);
+		parm[3]  = (p_dtd->horz_blanking & 0xFF);
+		parm[4]  = ((p_dtd->horz_active & 0xF00) >> 4) |
+					((p_dtd->horz_blanking & 0xF00) >> 8);
+	}
+	parm[5]  = (p_dtd->vert_active & 0xFF);
+	parm[6]  = (p_dtd->vert_blanking & 0xFF);
+	parm[7]  = ((p_dtd->vert_active & 0xF00) >> 4) |
+				((p_dtd->vert_blanking & 0xF00) >> 8);
+	parm[8]  = (p_dtd->horz_sync_offset & 0xFF);
+	parm[9]  = (p_dtd->horz_sync_pulse_width & 0xFF);
+	parm[10] = ((p_dtd->vert_sync_offset & 0x0F) << 4) |
+				(p_dtd->vert_sync_pulse_width & 0x0F);
+	parm[11] = ((p_dtd->horz_sync_offset & 0x300) >> 2) |
+			   ((p_dtd->horz_sync_pulse_width & 0x300) >> 4) |
+			   ((p_dtd->vert_sync_offset & 0x30) >> 2) |
+			   ((p_dtd->vert_sync_pulse_width & 0x30) >> 4);
+	parm[12] = p_dtd->dtd_flags;
+	parm[13] = p_dtd->sdvo_flags;
+	parm[14] = p_dtd->vert_sync_offset & 0xC0;
+}
+
+#ifndef CONFIG_MICRO
+sdvo_status_t sdvo_get_min_max_pixel_clock(sdvo_device_context_t *p_ctx,
+	unsigned long *p_min_clock,
+	unsigned long *p_max_clock)
+{
+	sdvo_status_t status;
+	sdvo_clock_rate_mult_t clock_mult;
+	unsigned short in_range[2], out_range[2];
+
+	status = sdvo_get_clock_rate_multiplier(p_ctx, &clock_mult);
+	if (status != SS_SUCCESS) {
+
+		return status;
+	}
+
+	status = sdvo_get_input_pixel_clock_range(p_ctx, in_range);
+	if (status != SS_SUCCESS) {
+
+		return status;
+	}
+
+	status = sdvo_get_output_pixel_clock_range(p_ctx, out_range);
+	if (status != SS_SUCCESS) {
+
+		return status;
+	}
+
+	switch (clock_mult)
+	{
+		case CRM_1X :
+			break;
+
+		case CRM_2X :
+			in_range[0] *= 2;
+			break;
+
+		case CRM_4X :
+			in_range[0] *= 4;
+			break;
+
+		default :
+			return SS_INVALID_RETURN;
+	}
+
+	/*	Minimum pixel clock supported is the maximum of min input/output */
+	/*  pixel clock */
+	*p_min_clock = in_range[0] > out_range[0] ? in_range[0] : out_range[0];
+
+	/*	Maximum pixel clock supported is minimum of max pixel clock of */
+	/*	encoder and SDVO bus clock rate */
+	*p_max_clock = in_range[1] < out_range[1] ? in_range[1] : out_range[1];
+
+	return SS_SUCCESS;
+}
+#endif
+
+unsigned char sdvo_write_i2c_reg(sdvo_device_context_t *p_ctx, i2c_reg_t offset,
+	i2c_reg_t value)
+{
+	pd_reg_t reg_list[2];
+
+/*	PD_DEBUG("sdvo : W : 0x%02x, 0x%02x", offset, value); */
+
+	reg_list[0].reg = offset;
+	reg_list[0].value = value;
+
+	reg_list[1].reg = PD_REG_LIST_END;
+
+	if (p_ctx->p_callback->write_regs(p_ctx->p_callback->callback_context, reg_list,
+			PD_REG_I2C)) {
+
+		return FALSE;
+
+	}else {
+
+		return TRUE;
+	}
+}
+
+
+unsigned char sdvo_read_i2c_reg(sdvo_device_context_t *p_ctx, unsigned char offset,
+						i2c_reg_t *p_Value)
+{
+	pd_reg_t reg_list[2];
+
+	reg_list[0].reg = offset;
+	reg_list[1].reg = PD_REG_LIST_END;
+
+	if (p_ctx->p_callback->read_regs(p_ctx->p_callback->callback_context, reg_list,
+								   PD_REG_I2C)) {
+
+		return FALSE;
+
+	} else {
+
+		*p_Value = (i2c_reg_t)reg_list[0].value;
+
+/*		PD_DEBUG("sdvo : R : 0x%02x, 0x%02x", offset, *p_Value); */
+
+		return TRUE;
+	}
+}
diff --git a/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.h b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.h
new file mode 100644
index 0000000..e861af4
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_intf.h
@@ -0,0 +1,482 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sdvo_intf.h
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Definitions for SDVO interface
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _SDVO_INTF_H_
+#define _SDVO_INTF_H_
+
+/*  ......................................................................... */
+/*  Opcode, Status Code, Register definitions */
+
+typedef enum {
+    /*  General */
+    RESET = 0x1,
+    GET_DEVICE_CAPABILITIES,
+    GET_TRAINED_INPUTS,
+    GET_ACTIVE_OUTPUTS,
+    SET_ACTIVE_OUTPUTS,
+
+    /*  Picture Routing  */
+    GET_IN_OUT_MAP = 0x6,
+    SET_IN_OUT_MAP,
+
+    GET_ATTACHED_DISPLAYS = 0x0B,
+
+    /* Hot Plug */
+    GET_HOT_PLUG_SUPPORT = 0x0C,
+    SET_ACTIVE_HOT_PLUG,
+    GET_ACTIVE_HOT_PLUG,
+    GET_INTERRUPT_EVENT_SOURCE,
+
+    /*  Input/Output Timings */
+    SET_TARGET_INPUT = 0x10,
+    SET_TARGET_OUTUT,
+    GET_INPUT_TIMINGS_PART1,
+    GET_INPUT_TIMINGS_PART2,
+    SET_INPUT_TIMINGS_PART1,
+    SET_INPUT_TIMINGS_PART2,
+    SET_OUTPUT_TIMINGS_PART1,
+    SET_OUTPUT_TIMINGS_PART2,
+    GET_OUTPUT_TIMINGS_PART1,
+    GET_OUTPUT_TIMINGS_PART2,
+    CREATE_PREFERRED_INPUT_TIMINGS,
+    GET_PREFERRED_INPUT_TIMINGS_PART1,
+    GET_PREFERRED_INPUT_TIMINGS_PART2,
+    GET_INPUT_PIXEL_CLOCK_RANGE,
+    GET_OUTPUT_PIXEL_CLOCK_RANGE,
+    GET_SUPPORTED_SDVO_CLOCK_RATE_MULTIPLIERS,
+    GET_SDVO_CLOCK_RATE_MULTIPLIER,
+    SET_SDVO_CLOCK_RATE_MULTIPLIER,
+
+    GET_SUPPORTED_TV_OUTPUT_FORMATS = 0x27,
+    GET_TV_OUTPUT_FORMAT,
+    SET_TV_OUTPUT_FORMAT,
+
+    /*  Power Management */
+    GET_SUPPORTED_POWER_STATES = 0x2A,
+    GET_POWER_STATE,
+    SET_POWER_STATE,
+
+    /*  Panel Power Sequencing */
+    GET_MAX_PANEL_POWER_SEQUENCING_PARAMETER = 0x2D,
+    GET_PANEL_POWER_SEQUENCING_PARAMETER,
+    SET_PANEL_POWER_SEQUENCING_PARAMETER,
+
+    GET_MAX_BACKLIGHT_LEVEL,
+    GET_BACKLIGHT_LEVEL,
+    SET_BACKLIGHT_LEVEL,
+
+    GET_AMBIENT_LIGHT,
+    SET_AMBIENT_LIGHT,
+
+    SET_UPSCALAR_COEFFICIENTS = 0x36,
+
+    GET_SSC,
+    SET_SSC,
+
+    /*  Content Protection */
+    GET_ANCILLARY_VIDEO_INFORMATION,
+    SET_ANCILLARY_VIDEO_INFORMATION,
+
+    /*  Picture Enhancements */
+    GET_MAX_FLICKER_FILTER = 0x4D,
+    GET_FLICKER_FILTER,
+    SET_FLICKER_FILTER,
+
+    GET_ADAPTIVE_FLICKER_FILTER,
+    SET_ADAPTIVE_FLICKER_FILTER,
+
+    GET_MAX_2D_FLICKER_FILTER,
+    GET_2D_FLICKER_FILTER,
+    SET_2D_FLICKER_FILTER,
+
+    GET_MAX_SATURATION,
+    GET_SATURATION,
+    SET_SATURATION,
+
+    GET_MAX_HUE,
+    GET_HUE,
+    SET_HUE,
+
+    GET_MAX_BRIGHTNESS,
+    GET_BRIGHTNESS,
+    SET_BRIGHTNESS,
+
+    GET_MAX_CONTRAST,
+    GET_CONTRAST,
+    SET_CONTRAST,
+
+    GET_MAX_HORIZONTAL_OVERSCAN,
+    GET_HORIZONTAL_OVERSCAN,
+    SET_HORIZONTAL_OVERSCAN,
+
+    GET_MAX_VERTICAL_OVERSCAN,
+    GET_VERTICAL_OVERSCAN,
+    SET_VERTICAL_OVERSCAN,
+
+    GET_MAX_HORIZONTAL_POSITION,
+    GET_HORIZONTAL_POSITION,
+    SET_HORIZONTAL_POSITION,
+
+    GET_MAX_VERTICAL_POSITION,
+    GET_VERTICAL_POSITION,
+    SET_VERTICAL_POSITION,
+
+    GET_MAX_SHARPNESS,
+    GET_SHARPNESS,
+    SET_SHARPNESS,
+
+    GET_DOT_CRAWL,
+    SET_DOT_CRAWL,
+
+    GET_DITHER,
+    SET_DITHER,
+
+    GET_MAX_TV_CHROMA_FILTER,
+    GET_TV_CHROMA_FILTER,
+    SET_TV_CHROMA_FILTER,
+
+    GET_MAX_TV_LUMA_FILTER,
+    GET_TV_LUMA_FILTER,
+    SET_TV_LUMA_FILTER,
+
+    /*  Control Bus Switch */
+    SET_CONTROL_BUS_SWITCH = 0x7A,
+
+    /*  Picture Enhancements */
+    GET_MAX_ADAPTIVE_FLICKER_FILTER = 0x7B,
+
+    /*  Power Management */
+    SET_DISPLAY_POWER_STATE = 0x7D,
+
+    /*  Panel Power Sequencing */
+    GET_MAX_SSC = 0x7E,
+    GET_LVDS_PANEL_INFORMATION,
+    SET_LVDS_PANEL_INFORMATION,
+    GET_LVDS_PANEL_PROTECTION,
+    SET_LVDS_PANEL_PROTECTION,
+
+	GET_SDTV_RESOLUTION_SUPPORT = 0x83,
+	GET_SUPPORTED_ENHANCEMENTS,
+	GET_SCALED_HDTV_RESOLUTION_SUPPORT,
+
+	/*  General */
+	GET_FIRMWARE_VERSION = 0x86,
+	DETECT_LEGACY_VGA = 0x87,
+
+	/* HDMI */
+	PREPARE_TO_GENERATE_HDCPAN = 0x8A,
+	SET_PIXEL_REPLICATION = 0x8B,
+	GET_PIXEL_REPLICATION,
+	GET_COLORIMETRY_CAPABILITIES,
+	SET_CURRENT_COLORIMETRY,
+	GET_CURRENT_COLORIMETRY,
+	GET_AUDIO_ENCRYPTION_PREFERENCE,
+	SET_AUDIO_STATE,
+	GET_AUDIO_STATE,
+	SET_HDMI_BUFFER_INDEX,
+	GET_HDMI_BUFFER_INDEX,
+	GET_HDMI_BUFFER_INFO,
+	SET_HDMI_BUFFER_AUDIO_VIDEO_SPLIT,
+	GET_HDMI_BUFFER_AUDIO_VIDEO_SPLIT,
+	SET_HDMI_BUFFER_DATA,
+	GET_HDMI_BUFFER_DATA,
+	SET_HDMI_BUFFER_TRANSMIT_RATE,
+	GET_HDMI_BUFFER_TRANSMIT_RATE,
+	GET_HDMI_AUDIO_TRANSMISSION_CHARACTERISTICS,
+	GET_SUPPORTED_DIGITAL_ENCODING_MODES, /* 0x9D, */
+	GET_DIGITAL_ENCODING_MODE,
+	SET_DIGITAL_ENCODING_MODE,
+} sdvo_opcode_t;
+
+typedef enum {
+    SS_POWER_ON_STATE,       /*  00: */
+    SS_SUCCESS,              /*  01: Command successfully completed */
+    SS_NOT_SUPPORTED,        /*  02: Invalid Opcode */
+    SS_INVALID_ARGUMENT,     /*  03: Opcode is valid but arguments are not */
+    SS_PENDING,              /*  04: Opcode is not completed yet */
+    SS_TARGET_UNSPECIFIED,   /*  05: SetTargetInput/Output not called */
+    SS_SCALING_UNSUPPORTED,  /*  06: Device does not support scaling */
+
+    /*  New Errors */
+    SS_UNSUCCESSFUL = 10,    /*  10: General Failure */
+    SS_INVALID_RETURN,       /*  11: Unexpected return value */
+    SS_WRITE_FAILED,         /*  12: Write Operation failed */
+    SS_READ_FAILED,          /*  13: Read Operation failed */
+} sdvo_status_t;
+
+#define SDVO_MAX_ARGS           8
+#define SDVO_MAX_RETURNS        8
+
+#define SDVO_REG_ARG_START      0x07
+#define SDVO_REG_ARG_END        0x00
+#define SDVO_REG_OPCODE         0x08
+#define SDVO_REG_STATUS         0x09
+#define SDVO_REG_RETURN_START   0x0A
+#define SDVO_REG_RETURN_END     0x11
+
+#define SDVO_MAX_RETRIES        3
+
+/*  ........................................................................ */
+/*  Structure definitions for Commands */
+
+typedef unsigned char i2c_reg_t;
+
+/* SDVOOutputFlagStructure Byte 0 */
+typedef struct {
+    i2c_reg_t tmds  : 1;
+    i2c_reg_t rgb   : 1;
+    i2c_reg_t cvbs  : 1;
+    i2c_reg_t svid  : 1;
+    i2c_reg_t yprpb : 1;
+    i2c_reg_t scart : 1;
+    i2c_reg_t lvds  : 1;
+    i2c_reg_t drgb  : 1;
+} sdvo_display_output_t;
+
+/* Display masks */
+#define FP_DISP_MASK (BIT(0)|BIT(6)|BIT(7)|BIT(8)|BIT(14)) /*TMDS/LVDS/DRGB*/
+#define TV_DISP_MASK (BIT(2)|BIT(3)|BIT(4)|BIT(5)) /*CVBS0/SVID0/YPRPB0/SCART0*/
+#define CRT_EXT_DISP_MASK (BIT(1)|BIT(9))   /* External CRT */
+#define LVDS_DISP_MASK    (BIT(6)|BIT(14))  /* LVDS */
+#define TMDS_DISP_MASK (BIT(0)|BIT(8))
+#define TV_SVIDEO_DISP_MASK (BIT(3))   /* S-VIDEO */
+#define TV_YPBPR_DISP_MASK (BIT(4))    /* YPBPR/Yipper */
+#define DRGB_DISP_MASK  (BIT(7))       /* DRGB0 */
+typedef struct {
+	union {
+		struct {
+			sdvo_display_output_t out0;
+			sdvo_display_output_t out1;
+		};
+		unsigned short flags;
+	};
+} sdvo_output_flags_t;
+
+typedef struct {
+    i2c_reg_t vendor_id;         /* 00: Vendor ID */
+    i2c_reg_t device_id;         /* 01: Device ID */
+    i2c_reg_t revision_id;       /* 02: Revision ID */
+    i2c_reg_t version_minor;     /*  03 : sDVO Minor Version (00) */
+    i2c_reg_t version_major;     /*  04 : sDVO Major Version (01) */
+                                 /*  05 : Device capabilities */
+    i2c_reg_t num_inputs    :2;  /*  10 : Number of sDVO inputs (1 or 2) */
+    i2c_reg_t smooth_scaling:1;  /*   2 : Smooth (Graphics) Scaling */
+    i2c_reg_t sharp_scaling :1;  /*   3 : Sharp (Text) scaling */
+    i2c_reg_t up_scaling    :1;  /*   4 : Up Scaling */
+    i2c_reg_t down_scaling  :1;  /*   5 : Down Scaling */
+    i2c_reg_t stall         :1;  /*   6 : Stall */
+    i2c_reg_t reserved      :1;  /*   7 : Reserved */
+    sdvo_output_flags_t output;  /* 06&07: Ouput supported by sDVO device */
+} sdvo_device_capabilities_t;
+
+typedef struct {
+    unsigned short pixel_clock;         /*  Pixel clock / 10,000 */
+    unsigned short active_horz_pixels;  /*  12 bits of horizontal active */
+    unsigned short active_vert_pixels;  /*  12 bits of vertical active */
+    unsigned char  b_interlaced :1;     /*  1:Interlaced, 0: Non-Interlaced */
+    unsigned char  b_scaled     :1;     /*  1:Image to be scaled, 0:Otherwise*/
+    unsigned char  resv_bits    :6;     /*  Reserved bits */
+    unsigned char  resv_byte;
+} sdvo_create_preferred_timings_t;
+
+typedef enum {
+    CRM_1X = BIT(0),
+    CRM_2X = BIT(1),
+    CRM_4X = BIT(3),
+} sdvo_clock_rate_mult_t;
+
+/*  Detailed Timing Descriptor */
+typedef struct {
+    unsigned short pixel_clock;      /*  Pixel Clock / 10,000 */
+    unsigned short horz_active;      /*  Horizontal Active */
+    unsigned short horz_blanking;    /*  Horizontal Blanking */
+    unsigned short vert_active;      /*  Vertical Active */
+    unsigned short vert_blanking;    /*  Vertical Blanking */
+    unsigned short horz_sync_offset;  /*  Pixels from blanking start */
+    unsigned short horz_sync_pulse_width;
+    unsigned char  vert_sync_offset;
+    unsigned char  vert_sync_pulse_width;
+    unsigned char  dtd_flags;
+    unsigned char  sdvo_flags;
+} sdvo_dtd_t;
+
+typedef enum {
+    SDVO0,
+    SDVO1,
+} sdvo_target_input_t;
+
+typedef struct {
+    i2c_reg_t dev_D0 :1; /*  SDVO On */
+    i2c_reg_t dev_D1 :1;
+    i2c_reg_t dev_D2 :1;
+    i2c_reg_t dev_D3 :1; /*  SDVO Off */
+    i2c_reg_t disp_D0:1; /*  Display On      : Vsync/Hsync/Video Active */
+    i2c_reg_t disp_D1:1; /*  Display Standby : Vsync Active, Hsync/Video Off */
+    i2c_reg_t disp_D2:1; /*  Display Suspend : Hsync Active, Vsync/Video Off */
+    i2c_reg_t disp_D3:1; /*  Display Off     : All signals Off */
+} sdvo_power_states_t;
+
+typedef struct {
+	struct{
+		i2c_reg_t minor_DVI_rev :4;
+		i2c_reg_t major_DVI_rev :4;
+	};
+	struct{
+		i2c_reg_t minor_HDMI_rev:4;
+		i2c_reg_t major_HDMI_rev:4;
+	};
+
+    i2c_reg_t reserved[6]; 		/* reserved for future use */
+} sdvo_digital_encode_modes_t;
+
+typedef struct{
+	sdvo_digital_encode_modes_t	version;
+}sdvo_hdmi_context_t;
+
+
+typedef struct _sdvo_device_context {
+    sdvo_target_input_t        inp_dev;
+    sdvo_output_flags_t        out_type;
+	sdvo_device_capabilities_t dev_cap;
+    pd_callback_t             *p_callback;
+	pd_attr_t                 *p_attr_table;
+	unsigned long              num_attrs;
+	pd_timing_t               *p_mode_table;
+	pd_timing_t               *native_dtd;
+	unsigned short             fp_width;
+	unsigned short             fp_height;
+	unsigned char              supp_pwr_states;
+	unsigned char              device_pwr_state, display_pwr_state;
+	unsigned char              up_scaling;
+	unsigned short             t1;   /* power state delays */
+	unsigned short             t2;   /* power state delays */
+	unsigned short             t3;   /* power state delays */
+	unsigned short             t4;
+	unsigned short             t5;
+	unsigned short             text_tune;
+	sdvo_hdmi_context_t		   hdmi;
+	unsigned short             st_sdvo;
+} sdvo_device_context_t;
+
+typedef struct sdvo_state {
+	unsigned long power_state;
+	pd_timing_t timing;
+} sdvo_state_t;
+
+/*  ......................................................................... */
+sdvo_status_t sdvo_execute_command(sdvo_device_context_t *p_ctx,
+	sdvo_opcode_t opcode,
+	i2c_reg_t num_args, i2c_reg_t *p_arg,
+	i2c_reg_t num_returns, i2c_reg_t *p_ret_value);
+
+sdvo_status_t sdvo_reset(sdvo_device_context_t *p_ctx);
+sdvo_status_t sdvo_get_device_capabilities(sdvo_device_context_t *p_ctx,
+	sdvo_device_capabilities_t *p_Dev_Cap);
+sdvo_status_t sdvo_get_trained_inputs(sdvo_device_context_t *p_ctx,
+	i2c_reg_t *p_Out);
+sdvo_status_t sdvo_get_active_outputs(sdvo_device_context_t *p_ctx,
+	sdvo_output_flags_t *p_Out_Flags);
+sdvo_status_t sdvo_set_active_outputs(sdvo_device_context_t *p_ctx,
+	sdvo_output_flags_t out_flags);
+
+sdvo_status_t sdvo_get_in_out_map(sdvo_device_context_t *p_ctx,
+	sdvo_output_flags_t out_flags[2]);
+sdvo_status_t sdvo_set_in_out_map(sdvo_device_context_t *p_ctx,
+	sdvo_output_flags_t out_flags[2]);
+sdvo_status_t sdvo_set_upscalar_coefficient(sdvo_device_context_t *p_ctx,
+	i2c_reg_t upscalar_coefficient);
+
+sdvo_status_t sdvo_get_attached_displays(sdvo_device_context_t *p_ctx,
+	sdvo_output_flags_t *p_Out_Flags);
+
+sdvo_status_t sdvo_set_target_input(sdvo_device_context_t *p_ctx,
+	sdvo_target_input_t input);
+sdvo_status_t sdvo_set_target_output(sdvo_device_context_t *p_ctx,
+	sdvo_output_flags_t out_flags);
+
+sdvo_status_t sdvo_get_input_timings(sdvo_device_context_t *p_ctx,
+	sdvo_dtd_t *p_dtd);
+sdvo_status_t sdvo_set_input_timings(sdvo_device_context_t *p_ctx,
+	sdvo_dtd_t *p_dtd);
+
+sdvo_status_t sdvo_get_output_timings(sdvo_device_context_t *p_ctx,
+	sdvo_dtd_t *p_dtd);
+sdvo_status_t sdvo_set_output_timings(sdvo_device_context_t *p_ctx,
+	sdvo_dtd_t *p_dtd);
+
+sdvo_status_t sdvo_get_input_pixel_clock_range(sdvo_device_context_t *p_ctx,
+	unsigned short p_Pixel[2]);
+
+sdvo_status_t sdvo_get_preferred_input_timings(sdvo_device_context_t *p_ctx,
+	sdvo_create_preferred_timings_t *p_Timings,
+	sdvo_dtd_t *p_dtd);
+sdvo_status_t sdvo_get_clock_rate_multiplier(sdvo_device_context_t *p_ctx,
+	sdvo_clock_rate_mult_t *p_mult);
+sdvo_status_t sdvo_set_clock_rate_multiplier(sdvo_device_context_t *p_ctx,
+	sdvo_clock_rate_mult_t mult);
+
+sdvo_status_t sdvo_get_supported_power_states(sdvo_device_context_t *p_ctx,
+	i2c_reg_t *p_pwr_state);
+sdvo_status_t sdvo_get_power_state(sdvo_device_context_t *p_ctx,
+	i2c_reg_t *p_Power_State);
+sdvo_status_t sdvo_set_power_state(sdvo_device_context_t *p_ctx,
+	i2c_reg_t pwr_state);
+sdvo_status_t sdvo_set_display_power_state(sdvo_device_context_t *p_ctx,
+	i2c_reg_t display_state);
+#if !defined(CONFIG_MICRO) /* These are not used in vBIOS */
+sdvo_status_t sdvo_set_digital_encoding_mode(sdvo_device_context_t *p_ctx,
+	i2c_reg_t digital_encoding_mode);
+sdvo_status_t sdvo_get_hdmi_audio_transmission_char(
+	sdvo_device_context_t *p_ctx, i2c_reg_t *hdmi_reg);
+sdvo_status_t sdvo_get_supported_encoding_modes(sdvo_device_context_t *p_ctx,
+    sdvo_digital_encode_modes_t *digital_encoding_modes);
+sdvo_status_t sdvo_get_digital_encoding_mode(sdvo_device_context_t *p_ctx,
+	i2c_reg_t *digital_encoding_mode);
+/* ------------------------------------------------------------------------- */
+#endif
+sdvo_status_t sdvo_get_min_max_pixel_clock(sdvo_device_context_t *p_ctx,
+	unsigned long *p_min_clock, unsigned long *p_max_clock);
+
+sdvo_status_t sdvo_get_tv_output_format(sdvo_device_context_t *p_ctx,
+	i2c_reg_t *p_TV_Output_Format_Flag);
+
+sdvo_status_t sdvo_get_sdtv_resolution_support(sdvo_device_context_t *p_ctx,
+	i2c_reg_t *p_Requested_SDTV_Format_Flag, i2c_reg_t *p_Resolution_Support_Flags);
+
+sdvo_status_t sdvo_get_scaled_hdtv_resolution_support(
+	sdvo_device_context_t *p_ctx, i2c_reg_t *p_Requested_HDTV_Format_Flag,
+	i2c_reg_t *p_Resolution_Support_Flags);
+
+sdvo_status_t sdvo_execute_command_read(sdvo_device_context_t *p_ctx,
+	i2c_reg_t num_returns, i2c_reg_t *p_ret_value);
+
+#endif  /*  _SDVO_INTF_H_ */
+
diff --git a/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.c b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.c
new file mode 100644
index 0000000..7651199
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.c
@@ -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/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.h b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.h
new file mode 100644
index 0000000..b06fc73b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/pal/sdvo/sdvo_port.h
@@ -0,0 +1,71 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: sdvo_port.h
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Main include file for SDVO port driver
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _SDVO_PORT_H_
+#define _SDVO_PORT_H_
+
+#include <config.h>
+#include <igd_pd.h>
+#include <pd.h>
+#include <pd_print.h>
+
+/* #define DEBUG 0 */
+
+/*  ............................................................................ */
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(p) (sizeof(p)/sizeof((p)[0]))
+#endif
+
+#include "sdvo_intf.h"
+#include "sdvo_attr.h"
+#include "sdvo_hdmi.h"
+
+/*  ............................................................................ */
+#ifndef CONFIG_MICRO
+#define	SDVO_GET_ATTR_NAME(p_attr)	p_attr->name
+#else
+#define SDVO_GET_ATTR_NAME(p_attr)	""
+#endif
+
+/*  ............................................................................ */
+unsigned char sdvo_write_i2c_reg(sdvo_device_context_t *p_Ctx, i2c_reg_t offset,
+	i2c_reg_t value);
+unsigned char sdvo_read_i2c_reg(sdvo_device_context_t *p_Ctx, unsigned char offset,
+	i2c_reg_t *p_Value);
+
+
+int sdvo_is_multi_display_device(sdvo_device_context_t *p_ctx);
+
+/*OKI Workaround*/
+#define	VENDOR_ID_OKI 0x81
+
+
+#endif  /*  _SDVO_PORT_H_ */
diff --git a/drivers/gpu/drm/emgd/emgd/state/appcontext/cmn/appcontext_dispatch.h b/drivers/gpu/drm/emgd/emgd/state/appcontext/cmn/appcontext_dispatch.h
new file mode 100644
index 0000000..3da03e0
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/appcontext/cmn/appcontext_dispatch.h
@@ -0,0 +1,56 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: appcontext_dispatch.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+#ifndef _APPCONTEXT_DISPATCH_H
+#define _APPCONTEXT_DISPATCH_H
+
+typedef struct _appcontext_table_t {
+	unsigned long appcontext_id;
+	unsigned long logical_context_offset;
+} appcontext_table_t;
+
+typedef struct _appcontext_dispatch_t {
+	int (*appcontext_init)(igd_context_t *context);
+	void (*appcontext_shutdown)(igd_context_t *context);
+	igd_appcontext_h (*appcontext_alloc)(igd_display_h display_handle,
+		int priority, unsigned int flags);
+	void (*appcontext_free)(igd_display_h display_handle,
+		int priority, igd_appcontext_h context_handle);
+	appcontext_table_t *table;
+} appcontext_dispatch_t;
+
+
+extern appcontext_dispatch_t appcontext_dispatch_plb;
+
+extern appcontext_dispatch_t *appcontext_dispatch;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/state/appcontext/cmn/igd_appcontext.c b/drivers/gpu/drm/emgd/emgd/state/appcontext/cmn/igd_appcontext.c
new file mode 100755
index 0000000..c5ee392
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/appcontext/cmn/igd_appcontext.c
@@ -0,0 +1,148 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_appcontext.c
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file inplements the IGD interface for the context module. This
+ *  includes functions that handle hardware context swapping and state
+ *  variable management.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.state
+
+#include <config.h>
+
+#include <igd_appcontext.h>
+#include <igd_gmm.h>
+#include <igd_mode.h>
+#include <igd_errno.h>
+
+#include <intelpci.h>
+#include <context.h>
+#include <mode.h>
+#include <dispatch.h>
+
+#include <io.h>
+
+#include "appcontext_dispatch.h"
+
+/*!
+ * @addtogroup state_group
+ * @{
+ */
+
+static dispatch_table_t appcontext_dispatch_list[] = {
+#ifdef CONFIG_PLB
+	{PCI_DEVICE_ID_VGA_PLB, &appcontext_dispatch_plb},
+#endif
+#ifdef CONFIG_TNC
+	{PCI_DEVICE_ID_VGA_TNC, &appcontext_dispatch_plb},
+#endif
+	{0, NULL}
+};
+
+/* Not static: cores may need it */
+appcontext_dispatch_t *appcontext_dispatch = NULL;
+
+/*!
+ *
+ * @param display_handle
+ * @param priority
+ * @param flags
+ *
+ * @return appcontext_h
+ */
+igd_appcontext_h igd_appcontext_alloc(
+	igd_display_h display_handle,
+	int priority,
+	unsigned int flags)
+{
+
+	return appcontext_dispatch->appcontext_alloc(
+		display_handle, priority, flags);
+}
+
+/*!
+ *
+ * @param display_handle
+ * @param priority
+ * @param appcontext_handle
+ *
+ * @return void
+ */
+void igd_appcontext_free(
+	igd_display_h display_handle,
+	int priority,
+	igd_appcontext_h appcontext_handle)
+{
+	appcontext_dispatch->appcontext_free(
+		display_handle, priority, appcontext_handle);
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+void appcontext_shutdown(igd_context_t *context)
+{
+
+	EMGD_DEBUG("appcontext_shutdown Entry");
+
+	if (appcontext_dispatch != NULL)
+	{
+		appcontext_dispatch->appcontext_shutdown(context);
+	}
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+int appcontext_init(igd_context_t *context)
+{
+
+	EMGD_DEBUG("appcontext_init Entry");
+
+	appcontext_dispatch = (appcontext_dispatch_t *)dispatch_acquire(context,
+		appcontext_dispatch_list);
+	if(!appcontext_dispatch) {
+		return -IGD_ERROR_NODEV;
+	}
+
+	/* Hook up top level dispatch table */
+	context->dispatch.appcontext_alloc = appcontext_dispatch->appcontext_alloc;
+	context->dispatch.appcontext_free = appcontext_dispatch->appcontext_free;
+
+	/* Hook up optional inter-module functions */
+	context->mod_dispatch.appcontext_shutdown = appcontext_shutdown;
+
+	return 0;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/state/appcontext/plb/appcontext_plb.c b/drivers/gpu/drm/emgd/emgd/state/appcontext/plb/appcontext_plb.c
new file mode 100644
index 0000000..568e24f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/appcontext/plb/appcontext_plb.c
@@ -0,0 +1,207 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: appcontext_plb.c
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file inplements the IGD interface for the context module. This
+ *  includes functions that handle hardware context swapping and state
+ *  variable management.
+ *-----------------------------------------------------------------------------
+ */
+
+#include <io.h>
+
+#include <igd_appcontext.h>
+#include <igd_gmm.h>
+#include <igd_mode.h>
+#include <igd_render.h>
+#include <igd_errno.h>
+
+#include <intelpci.h>
+#include <memory.h>
+#include <mode_access.h>
+#include <context.h>
+#include <state2d.h>
+#include <mode.h>
+#include <dispatch.h>
+#include <utils.h>
+
+#include <plb/appcontext.h>
+#include <plb/instr.h>
+#include <plb/state3d_plb.h>
+
+#include "../cmn/appcontext_dispatch.h"
+
+/*!
+ * @addtogroup state_group
+ * @{
+ */
+
+/*
+ * Prototype these here because they are only needed by appcontext.c
+ * and putting them in state2d.h would cause a circular dependency.
+ */
+
+static igd_appcontext_h igd_appcontext_alloc_plb(
+	igd_display_h display_handle,
+	int priority,
+	unsigned int flags);
+static void igd_appcontext_free_plb(
+	igd_display_h display_h,
+	int priority,
+	igd_appcontext_h appcontext_handle);
+static int appcontext_init_plb(igd_context_t *context);
+static void appcontext_shutdown_plb(igd_context_t *context);
+
+static appcontext_table_t appcontext_table_plb[] = {
+	{0, 0}
+};
+
+appcontext_dispatch_t appcontext_dispatch_plb = {
+	appcontext_init_plb,
+	appcontext_shutdown_plb,
+	igd_appcontext_alloc_plb,
+	igd_appcontext_free_plb,
+	appcontext_table_plb
+};
+
+/*!
+ *
+ * @param appcontext
+ *
+ * @return 0 on success
+ * @return -IGD_ERROR_NOMEM on failure
+ */
+static int state2d_init_plb(appcontext_t *appcontext)
+{
+
+	appcontext->state2d = OS_ALLOC(sizeof(state2d_t));
+	if(!appcontext->state2d) {
+		return -IGD_ERROR_NOMEM;
+	}
+
+	STATE2D(appcontext)->clip_status = IGD_CLIP_DISABLED;
+	STATE2D(appcontext)->dest_rect.x1 = 0;
+	STATE2D(appcontext)->dest_rect.y1 = 0;
+	STATE2D(appcontext)->dest_rect.x2 = 0;
+	STATE2D(appcontext)->dest_rect.y2 = 0;
+
+	return 0;
+}
+
+/*!
+ *
+ * @param appcontext
+ *
+ * @return void
+ */
+static int state2d_shutdown_plb(appcontext_t *appcontext)
+{
+	if(appcontext->state2d) {
+		OS_FREE(appcontext->state2d);
+	}
+
+	appcontext->state2d = NULL;
+
+	return 0;
+}
+
+/*!
+ *
+ * @param display_handle
+ * @param priority
+ * @param flags
+ *
+ * @return appcontext_h on success
+ * @return NULL on failure
+ */
+static igd_appcontext_h igd_appcontext_alloc_plb(
+	igd_display_h display_handle,
+	int priority,
+	unsigned int flags)
+{
+	appcontext_t *appcontext;
+
+	/* A proper appcontext is not required for Poulsbo
+	 * as a result, we'll allocate it and have it set to NULL
+	 */
+	appcontext = OS_ALLOC(sizeof(appcontext_t));
+	if (!appcontext) {
+		EMGD_ERROR ("OS_ALLOC appcontext failed\n");
+		return NULL;
+	}
+
+	OS_MEMSET(appcontext, 0, sizeof(appcontext_t));
+	appcontext->state2d = NULL;
+
+	if (flags & IGD_CONTEXT_STATE_2D) {
+		if (state2d_init_plb(appcontext)) {
+			igd_appcontext_free_plb(display_handle, priority, appcontext);
+			return NULL;
+		}
+	}
+
+	return appcontext;
+
+}
+
+static void igd_appcontext_free_plb(
+	igd_display_h display_h,
+	int priority,
+	igd_appcontext_h appcontext_handle)
+{
+
+	appcontext_t *appcontext = (appcontext_t *)appcontext_handle;
+
+	/* Free the appcontext struct */
+	if (appcontext) {
+		state2d_shutdown_plb(appcontext);
+
+		OS_FREE(appcontext_handle);
+	}
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return 0
+ */
+static int appcontext_init_plb(igd_context_t *context)
+{
+	return 0;
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return void
+ */
+static void appcontext_shutdown_plb(igd_context_t *context)
+{
+	return;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/state/power/cmn/igd_pwr.c b/drivers/gpu/drm/emgd/emgd/state/power/cmn/igd_pwr.c
new file mode 100644
index 0000000..2cfd775
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/power/cmn/igd_pwr.c
@@ -0,0 +1,305 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_pwr.c
+ * $Revision: 1.15 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.power
+
+#include <config.h>
+#include <io.h>
+
+#include <igd_init.h>
+#include <igd_errno.h>
+#include <igd_pwr.h>
+#include <igd_mode.h>
+
+#include <module_init.h>
+#include <mode.h>
+#include <dsp.h>
+#include <intelpci.h>
+#include <dispatch.h>
+#include "pwr_dispatch.h"           /* contains the power dispatch functions */
+
+/*!
+ * @addtogroup state_group
+ * @{
+ */
+
+static dispatch_table_t pwr_dispatch_list[] = {
+#ifdef CONFIG_PLB
+	{PCI_DEVICE_ID_VGA_PLB, &pwr_dispatch_plb},
+#endif
+#ifdef CONFIG_TNC
+	{PCI_DEVICE_ID_VGA_TNC, &pwr_dispatch_plb},
+#endif
+	{0, NULL}
+};
+
+typedef struct _power_context {
+	pwr_dispatch_t *dispatch;
+	void *power_state;
+} power_context_t;
+
+static power_context_t power_context;
+
+static int igd_pwr_query(igd_driver_h driver_handle, unsigned int power_state)
+{                                                           /* igd_pwr_query */
+	return power_context.dispatch->pwr_query(power_state);
+}                                                           /* igd_pwr_query */
+
+/*!
+ * This function alters the power state of the graphics device.  This
+ * function saves and restores registers as necessary and changes the
+ * power states of the mode and overlay module.
+ *
+ * This function will convert a request for D2 to a request for D1.
+ *
+ * @param driver_handle driver context
+ * @param dwPowerState power state to set the device to.
+ *
+ * @return < 0 on Error
+ * @return 0 on Success
+ */
+static int igd_pwr_alter(igd_driver_h driver_handle, unsigned int dwPowerState)
+{                                                           /* igd_pwr_alter */
+	unsigned char *mmio;
+	int           retval   = 0;
+	igd_context_t *context = (igd_context_t *) driver_handle;
+
+	EMGD_DEBUG("in igd_pwr_alter");
+
+	EMGD_DEBUG("Power State requested: 0x%x", dwPowerState);
+
+	if(context == NULL) {
+		EMGD_ERROR("In igd_pwr_alter:-Device context is null");
+		return -IGD_ERROR_INVAL;
+	}
+
+	if(power_context.power_state == NULL) {
+		EMGD_DEBUG("In igd_pwr_alter:- Memory not allocated yet."
+				" Power Module Not Initialised");
+		return -IGD_ERROR_INVAL;
+	}
+
+	mmio = context->device_context.virt_mmadr;
+
+	if(context->device_context.power_state == dwPowerState ) {
+		EMGD_DEBUG("Already in the present state");
+		return -IGD_ERROR_INVAL;
+	}
+
+	switch(dwPowerState) {
+	case IGD_POWERSTATE_D0:
+		/* Do any chipset specific power management */
+		retval = power_context.dispatch->pwr_set(context, dwPowerState);
+
+		/* restore the registers */
+		retval = context->mod_dispatch.reg_restore(context,
+			power_context.power_state);
+		if (retval) {
+			return retval;
+		}
+
+		/* Officially change the power state after registers are restored */
+		context->device_context.power_state = IGD_POWERSTATE_D0;
+
+		/* Power up mode module */
+		if(context->mod_dispatch.mode_pwr) {
+			retval = context->mod_dispatch.mode_pwr(context, dwPowerState);
+			if (retval) {
+				return retval;
+			}
+		}
+
+		/* enable overlay */
+		if(context->mod_dispatch.overlay_pwr) {
+			context->mod_dispatch.overlay_pwr(context, IGD_POWERSTATE_D0);
+		}
+
+		/* enable msvdx */
+		if(context->mod_dispatch.msvdx_pwr) {
+			context->mod_dispatch.msvdx_pwr(context, IGD_POWERSTATE_D0);
+		}
+		break;
+
+	case IGD_POWERSTATE_D1:
+	case IGD_POWERSTATE_D2:
+		/* Standby - ACPI S1 */
+
+		if (IGD_POWERSTATE_D2 == dwPowerState) {
+			dwPowerState = IGD_POWERSTATE_D1;
+		}
+
+
+		/* Turn off the msvdx */
+		if(context->mod_dispatch.msvdx_pwr) {
+			context->mod_dispatch.msvdx_pwr(context, dwPowerState);
+		}
+
+		/* Turn off the overlay */
+		if(context->mod_dispatch.overlay_pwr) {
+			context->mod_dispatch.overlay_pwr(context, dwPowerState);
+		}
+
+		/* save registers */
+		retval = context->mod_dispatch.reg_save(context,
+			power_context.power_state);
+		if (retval) {
+			return retval;
+		}
+
+		/* Change the state of the device to Dx.  This is required so the
+		 * plane/pipe/port all use this.  This needs to happen after "reg_save"
+		 * because igd_sync will timeout if power state is not D0
+		 */
+		context->device_context.power_state = dwPowerState;
+
+		if(context->mod_dispatch.mode_pwr) {
+			retval = context->mod_dispatch.mode_pwr(context, dwPowerState);
+			if (retval) {
+				return retval;
+			}
+		}
+
+		/* Do any chipset specific power management */
+		retval = power_context.dispatch->pwr_set(context, dwPowerState);
+
+		break;
+
+	case IGD_POWERSTATE_D3:
+		/* Suspend to memory - ACPI S3 */
+
+		/* diable msvdx */
+		if(context->mod_dispatch.msvdx_pwr) {
+			context->mod_dispatch.msvdx_pwr(context, dwPowerState);
+		}
+
+		/* disable overlay */
+		if(context->mod_dispatch.overlay_pwr) {
+			context->mod_dispatch.overlay_pwr(context, dwPowerState);
+		}
+
+		/* save registers */
+		retval= context->mod_dispatch.reg_save(context,
+			power_context.power_state);
+		if (retval) {
+			return retval;
+		}
+
+		/* Change the state of the device to Dx.  This is required so the
+		 * plane/pipe/port all use this.  This needs to happen after "reg_save"
+		 * because igd_sync will timeout if power state is not D0
+		 */
+		context->device_context.power_state = dwPowerState;
+
+		/* Mode module Power */
+		if(context->mod_dispatch.mode_pwr) {
+			retval = context->mod_dispatch.mode_pwr(context, dwPowerState);
+			if (retval) {
+				return retval;
+			}
+		}
+
+
+		/* Do any chipset specific power management */
+		retval = power_context.dispatch->pwr_set(context, dwPowerState);
+
+		break;
+
+	default:
+		/* state undefined */
+		EMGD_ERROR("In igd_pwr_alter:-Undefined Power State");
+		break;
+
+	}
+
+	return retval;
+}                                                           /* igd_pwr_alter */
+
+/*!
+ * This function should be called from context manager.
+ * To delete the memory allocated ealier.
+ *
+ * @param context
+ *
+ * @return void
+ */
+static void _pwr_shutdown(igd_context_t *context)
+{
+
+	if(power_context.power_state) {
+		context->mod_dispatch.reg_free(context, power_context.power_state);
+	}
+	power_context.power_state = NULL;
+	context->device_context.power_state = IGD_POWERSTATE_UNDEFINED;
+	return;
+}
+
+/*!
+ * This function should only be called only once from context manager .
+ * It initializes the power module.
+ *
+ * @param context
+ *
+ * @return < 0 on Error
+ * @return 0 on Success
+ */
+int _pwr_init(igd_context_t *context)
+{                                                               /* _pwr_init */
+	EMGD_ASSERT(context, "Null Context", -IGD_ERROR_INVAL);
+
+	/* Hook up the IGD dispatch table entires for power */
+	context->dispatch.pwr_alter = igd_pwr_alter;
+	context->dispatch.pwr_query = igd_pwr_query;
+
+	/* Inter-module dispatch */
+	context->mod_dispatch.pwr_shutdown = _pwr_shutdown;
+
+	power_context.dispatch = (pwr_dispatch_t *)dispatch_acquire(context,
+		pwr_dispatch_list);
+
+	if(!power_context.dispatch) {
+		return -IGD_ERROR_NODEV;
+	}
+
+	/* Initialize chipset specific default power behavior */
+	power_context.dispatch->pwr_init(context);
+
+	power_context.power_state = context->mod_dispatch.reg_alloc(context,
+		IGD_REG_SAVE_VGA |
+		IGD_REG_SAVE_DAC | IGD_REG_SAVE_MMIO | IGD_REG_SAVE_RB |
+		IGD_REG_SAVE_MODE | IGD_REG_SAVE_3D );
+
+	if(!power_context.power_state) {
+		return -IGD_ERROR_NOMEM;
+	}
+
+	return 0;
+}                                                               /* _pwr_init */
+
diff --git a/drivers/gpu/drm/emgd/emgd/state/power/cmn/pwr_dispatch.h b/drivers/gpu/drm/emgd/emgd/state/power/cmn/pwr_dispatch.h
new file mode 100644
index 0000000..34043ba
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/power/cmn/pwr_dispatch.h
@@ -0,0 +1,52 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pwr_dispatch.h
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains the protocols for the plaform-specific dispatch
+ *  functions that the power module uses.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _PWR_DISPATCH_H
+#define _PWR_DISPATCH_H
+
+#include <context.h>
+
+typedef struct _pwr_dispatch {
+	/* Queries support for power_state
+	 * ret:  0 if power_state is supported, <0 otherwise
+	 */
+	int (*pwr_query)(unsigned int power_state);
+	/* Dispatch function to set device dependent part of set power */
+	int (*pwr_set)(igd_context_t *context, unsigned int power_state);
+	/* Dispatch function to set init time device dependent power settings */
+	int (*pwr_init)(igd_context_t *context);
+} pwr_dispatch_t;
+
+extern pwr_dispatch_t pwr_dispatch_plb;
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/emgd/state/power/plb/pwr_plb.c b/drivers/gpu/drm/emgd/emgd/state/power/plb/pwr_plb.c
new file mode 100644
index 0000000..22d3280
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/power/plb/pwr_plb.c
@@ -0,0 +1,123 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pwr_plb.c
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+/* copied from napa */
+
+#include <io.h>
+#include "igd_pwr.h"
+#include "../cmn/pwr_dispatch.h"
+#include <plb/regs.h>
+
+/*!
+ * @addtogroup state_group
+ * @{
+ */
+
+static int pwr_query_full_plb(unsigned int power_state);
+static int pwr_set_plb(igd_context_t *context, unsigned int power_state);
+static int pwr_init_plb(igd_context_t *context);
+
+pwr_dispatch_t pwr_dispatch_plb = {
+	pwr_query_full_plb,
+	pwr_set_plb,
+	pwr_init_plb,
+};
+
+/*!
+ * This function returns "0" for all ACPI system states.
+ *
+ * @param power_state the requested power state
+ *
+ * @return 0
+ */
+static int pwr_query_full_plb(unsigned int power_state)
+{                                                          /* pwr_query_full */
+	switch( power_state ) {
+
+	case IGD_ADAPTERPOWERSTATE_ON:
+	case IGD_ADAPTERPOWERSTATE_STANDBY:
+	case IGD_ADAPTERPOWERSTATE_OFF:
+	case IGD_ADAPTERPOWERSTATE_SUSPEND:
+	case IGD_ADAPTERPOWERSTATE_HIBERNATE:
+	default:
+		return 0;
+		break;
+	}
+}                                                          /* pwr_query_full */
+
+/*!
+ *
+ * @patam context
+ * @param power_state the requested power state
+ *
+ * @return 0
+ */
+static int pwr_set_plb(igd_context_t *context, unsigned int power_state)
+{
+	unsigned char *mmio;
+
+	mmio = context->device_context.virt_mmadr;
+
+	switch (power_state) {
+	case IGD_POWERSTATE_D0:
+		break;
+	case IGD_POWERSTATE_D1:
+		break;
+	case IGD_POWERSTATE_D2:
+		break;
+	case IGD_POWERSTATE_D3:
+		break;
+
+	default:
+		break;
+	}
+	return 0;
+}
+
+/*!
+ *
+ * @param context
+ *
+ * @return 0
+ */
+static int pwr_init_plb(igd_context_t *context)
+{
+	unsigned char *mmio;
+
+	mmio = context->device_context.virt_mmadr;
+
+	/* Reset CLKGATECTL and CLKGATECTLOVR */
+	EMGD_WRITE32(0x1111111, mmio + PSB_CR_CLKGATECTL);
+	EMGD_WRITE32(0, mmio + PSB_CR_CLKGATECTL + 8);
+
+	return 0;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg.c b/drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg.c
new file mode 100644
index 0000000..e030f0d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg.c
@@ -0,0 +1,451 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: reg.c
+ * $Revision: 1.16 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the implementation file for the register module's main API's called
+ *  by external devices.
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.state
+
+#include <io.h>
+
+#include <igd_init.h>
+#include <igd_mode.h>
+#include <igd_errno.h>
+
+#include <context.h>
+#include <utils.h>
+#include <dsp.h>
+#include <mode.h>
+#include <memory.h>
+#include <utils.h>
+
+#include <intelpci.h>
+#include <dispatch.h>
+
+#include "reg_dispatch.h"
+
+/*!
+ * @addtogroup state_group
+ * @{
+ */
+
+typedef struct _reg_context {
+	unsigned long flags;     /* IGD_DRIVER_SAVE_RESTORE */
+	reg_dispatch_t *dispatch;
+	reg_buffer_t *device_state;
+	void *gmm_state;
+} reg_context_t;
+
+extern emgd_drm_config_t config_drm;
+static reg_context_t reg_ctx[1];
+static reg_buffer_t *console_state;
+void *console_gmm_state;
+static reg_buffer_t *misc_state;
+void *misc_gmm_state;
+
+static dispatch_table_t reg_dispatch_list[] = {
+
+#ifdef CONFIG_PLB
+	{PCI_DEVICE_ID_VGA_PLB, &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/drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg_dispatch.h b/drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg_dispatch.h
new file mode 100644
index 0000000..985fa44
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/reg/cmn/reg_dispatch.h
@@ -0,0 +1,73 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: reg_dispatch.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the implementation file for the register module's main API's called
+ *  by external devices.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _REG_DISPATCH_H
+#define _REG_DISPATCH_H
+
+#include <context.h>
+#include <drm_emgd_private.h>
+
+typedef struct _reg_buffer {
+	unsigned long flags;
+	module_state_h mode_buffer;
+	void *platform_buffer;
+}reg_buffer_t;
+
+/*
+ * This needs to be available for inter-module use so that the
+ * mode module can save state during it's init which happens after
+ * the reg module init.
+ */
+typedef struct _reg_dispatch {
+	reg_buffer_t *(*reg_alloc)(igd_context_t *context, unsigned long flags,
+		void *_platform_context);
+	void (*reg_free)(igd_context_t *context, reg_buffer_t *reg_set,
+		void *_platform_context);
+	int (*reg_save)(igd_context_t *context, reg_buffer_t *reg_set,
+		void *_platform_context);
+	int (*reg_restore)(igd_context_t *context, reg_buffer_t *reg_set,
+		void *_platform_context);
+	void (*reg_crtc_lut_get)(igd_context_t *context, emgd_crtc_t *emgd_crtc);
+	void (*reg_crtc_lut_set)(igd_context_t *context, emgd_crtc_t *emgd_crtc);
+	void *platform_context;
+} reg_dispatch_t;
+
+/*
+ * Reg dispatch data structure is in reg.h because it and the reg context
+ * needs to be available for initial reg save during mode module init.
+ */
+
+
+extern reg_dispatch_t reg_dispatch_plb;
+extern reg_dispatch_t reg_dispatch_tnc;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/state/reg/plb/reg_plb.c b/drivers/gpu/drm/emgd/emgd/state/reg/plb/reg_plb.c
new file mode 100644
index 0000000..d262ad6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/reg/plb/reg_plb.c
@@ -0,0 +1,1126 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: reg_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:
+ *  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 <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;
+} 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 *platform_context =
+		(reg_platform_context_plb_t *)_platform_context;
+	int                        i;
+	unsigned char              *mmio;
+
+	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,
+			platform_context->ar, platform_context->cr, platform_context->sr,
+			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; platform_context->mmio_regs[i] != 0xffffffff; i++) {
+			*buffer++ = EMGD_READ32(mmio + 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, 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);
+
+	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 *platform_context =
+		(reg_platform_context_plb_t *)_platform_context;
+	unsigned char *mmio;
+	unsigned long *buffer;
+	int i;
+
+	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; platform_context->mmio_regs[i] != 0xffffffff; i++) {
+			if (platform_context->mmio_regs[i] == MI_ARB_STATE) {
+				EMGD_DEBUG("Handle special masked register case");
+				EMGD_WRITE32(0x04100000 | *buffer++, mmio +
+					platform_context->mmio_regs[i]);
+			} else if (platform_context->mmio_regs[i] == DPLLACNTR ||
+				platform_context->mmio_regs[i] == DPLLBCNTR) {
+
+					EMGD_DEBUG("Handle special DPLL settling");
+					EMGD_WRITE32(*buffer++,
+						mmio + platform_context->mmio_regs[i]);
+					OS_SLEEP(150);
+			} else {
+				EMGD_WRITE32(*buffer++, mmio + 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, platform_context);
+	}
+
+	/* Restore VGA registers */
+	if (reg_buffer->flags & IGD_REG_SAVE_VGA) {
+		reg_restore_vga_plb(context, &reg_args->vga_state,
+			platform_context->ar, platform_context->cr, platform_context->sr,
+			platform_context->gr);
+	}
+
+	/* Restore the SGX clock gating settings */
+	EMGD_WRITE32(reg_args->clk_gating_ctl, mmio + PSB_CR_CLKGATECTL);
+
+	return 0;
+}
+
+/*!
+ * This function saves the GTT table entries into a buffer so that the GTT
+ * can be restored later.
+ *
+ * @param context needs this to get the GTT table size and to get the
+ *	virtual address to the GTT table
+ * @param mmio virtual address to MMIO
+ * @param reg_args a pre-allocated context where GTT entries are saved
+ *
+ * @return 0 on success
+ * @return -1 on failure
+ */
+static int reg_save_gtt_plb(igd_context_t *context, unsigned char *mmio,
+	reg_buffer_plb_t *reg_args)
+{
+	unsigned int  i;
+
+	/* Read the GTT entries from GTT ADR and save it in the array. */
+	for (i = 0; i < (context->device_context.gatt_pages); i++) {
+		reg_args->gtt[i] = EMGD_READ32(
+			context->device_context.virt_gttadr + i);
+	}
+
+	reg_args->sgx_phyaddr = EMGD_READ32(mmio + PSB_CR_BIF_DIR_LIST_BASE0);
+
+	return 0;
+}
+
+/*!
+ *  This function restores the GTT table entries.
+ *
+ * @param context the context contains the GTT size and address
+ * @param reg_args this has the saved GTT entries
+ *
+ * @return 0 on success
+ * @return -1 on failure
+ */
+static int reg_restore_gtt_plb(igd_context_t *context,
+	reg_buffer_plb_t *reg_args)
+{
+	unsigned int i;
+	unsigned char *mmio;
+	unsigned long sgx_mmu;
+
+	/* If the first element is 0, then nothing was saved */
+	if (0 == reg_args->gtt[0]) {
+		return 0;
+	}
+
+	/* Restore the GTT entries */
+	for (i=0; i < context->device_context.gatt_pages; i++) {
+		EMGD_WRITE32(reg_args->gtt[i],
+			context->device_context.virt_gttadr + i);
+	}
+
+	mmio = context->device_context.virt_mmadr;
+
+	/*
+	 * FIXME: This is probably not necessary and may be incorrect
+	 */
+	/* Invalidate directory cache */
+	sgx_mmu = EMGD_READ32(mmio + PSB_CR_BIF_CTRL);
+	sgx_mmu |= 0x1E;
+	EMGD_WRITE32(sgx_mmu, mmio + PSB_CR_BIF_CTRL);
+	EMGD_READ32(mmio + PSB_CR_BIF_CTRL);
+
+	EMGD_WRITE32(reg_args->sgx_phyaddr, mmio + PSB_CR_BIF_DIR_LIST_BASE0);
+	EMGD_READ32(mmio + PSB_CR_BIF_DIR_LIST_BASE0);
+
+	/* Turn on host access to aperture via the MMU */
+	sgx_mmu = EMGD_READ32(mmio + PSB_CR_BIF_CTRL);
+	sgx_mmu &= 0xFFFF0000;
+	EMGD_WRITE32(sgx_mmu, mmio + PSB_CR_BIF_CTRL);
+	EMGD_READ32(mmio + PSB_CR_BIF_CTRL);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/state/reg/tnc/reg_tnc.c b/drivers/gpu/drm/emgd/emgd/state/reg/tnc/reg_tnc.c
new file mode 100644
index 0000000..969155e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/state/reg/tnc/reg_tnc.c
@@ -0,0 +1,1205 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: reg_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 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 <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;
+} 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 *platform_context =
+		(reg_platform_context_tnc_t *)_platform_context;
+	int                        i;
+	unsigned char              *mmio, *mmio_sdvo, *mmio_sdvo_st, *mmio_sdvo_st_gpio;
+
+	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,
+			platform_context->ar, platform_context->cr, platform_context->sr,
+			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; platform_context->mmio_regs[i] != 0xffffffff; i++) {
+			*buffer++ = EMGD_READ32(mmio + platform_context->mmio_regs[i]);
+		}
+
+		buffer_sdvo = reg_args->mmio_state_sdvo;
+		for (i=0; platform_context->mmio_regs_sdvo[i] != 0xffffffff; i++) {
+			*buffer_sdvo++ = EMGD_READ32(mmio_sdvo + 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, 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);
+
+	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 *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;
+	int i;
+
+	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; platform_context->mmio_regs[i] != 0xffffffff; i++) {
+			if (platform_context->mmio_regs[i] == MI_ARB_STATE) {
+				EMGD_DEBUG("Handle special masked register case");
+				EMGD_WRITE32(0x04100000 | *buffer++, mmio +
+					platform_context->mmio_regs[i]);
+			} else if (platform_context->mmio_regs[i] == DPLLACNTR ||
+				platform_context->mmio_regs[i] == DPLLBCNTR) {
+
+					EMGD_DEBUG("Handle special DPLL settling");
+					EMGD_WRITE32(*buffer++,
+						mmio + platform_context->mmio_regs[i]);
+					OS_SLEEP(150);
+			} else {
+				EMGD_WRITE32(*buffer++, mmio + platform_context->mmio_regs[i]);
+			}
+		}
+//		reg_restore_gtt_tnc(context, reg_args);
+
+		buffer_sdvo = reg_args->mmio_state_sdvo;
+		for (i=0; platform_context->mmio_regs_sdvo[i] != 0xffffffff; i++) {
+			if (platform_context->mmio_regs_sdvo[i] == MI_ARB_STATE) {
+				EMGD_DEBUG("Handle special masked register case");
+				EMGD_WRITE32(0x04100000 | *buffer_sdvo++, mmio_sdvo +
+					platform_context->mmio_regs_sdvo[i]);
+			} else if (platform_context->mmio_regs_sdvo[i] == DPLLACNTR ||
+				platform_context->mmio_regs_sdvo[i] == DPLLBCNTR) {
+
+					EMGD_DEBUG("Handle special DPLL settling");
+					EMGD_WRITE32(*buffer_sdvo++,
+						mmio_sdvo + platform_context->mmio_regs_sdvo[i]);
+					OS_SLEEP(150);
+			} else {
+				EMGD_WRITE32(*buffer_sdvo++, mmio_sdvo + 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, platform_context);
+	}
+
+	/* Restore VGA registers */
+	if (reg_buffer->flags & IGD_REG_SAVE_VGA) {
+		reg_restore_vga_tnc(context, &reg_args->vga_state,
+			platform_context->ar, platform_context->cr, platform_context->sr,
+			platform_context->gr);
+	}
+
+	/* Restore the SGX clock gating settings */
+	EMGD_WRITE32(reg_args->clk_gating_ctl, mmio + PSB_CR_CLKGATECTL);
+
+	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/drivers/gpu/drm/emgd/emgd/utils/math_fix.c b/drivers/gpu/drm/emgd/emgd/utils/math_fix.c
new file mode 100644
index 0000000..84e5811
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/utils/math_fix.c
@@ -0,0 +1,138 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: math_fix.c
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains fixed point implementations of math functions
+ *-----------------------------------------------------------------------------
+ */
+
+
+/******************************************************************************
+ * This is a look-up table for natural log for integer values 1 - 255 in
+ * 24i.8f fixed point format.
+ *
+ * This table returns 0 or ln(0), but it is technically undefined.
+ *****************************************************************************/
+static const int ln_table[] =
+  {
+    0,    0,  177,  281,  355,  412,  459,  498,  532,  562,  589,  614,
+    636,  657,  676,  693,  710,  725,  740,  754,  767,  779,  791,  803,
+    814,  824,  834,  844,  853,  862,  871,  879,  887,  895,  903,  910,
+    917,  924,  931,  938,  944,  951,  957,  963,  969,  975,  980,  986,
+    991,  996, 1001, 1007, 1012, 1016, 1021, 1026, 1030, 1035, 1039, 1044,
+    1048, 1052, 1057, 1061, 1065, 1069, 1073, 1076, 1080, 1084, 1088, 1091,
+    1095, 1098, 1102, 1105, 1109, 1112, 1115, 1119, 1122, 1125, 1128, 1131,
+    1134, 1137, 1140, 1143, 1146, 1149, 1152, 1155, 1158, 1160, 1163, 1166,
+    1168, 1171, 1174, 1176, 1179, 1181, 1184, 1186, 1189, 1191, 1194, 1196,
+    1199, 1201, 1203, 1206, 1208, 1210, 1212, 1215, 1217, 1219, 1221, 1223,
+    1226, 1228, 1230, 1232, 1234, 1236, 1238, 1240, 1242, 1244, 1246, 1248,
+    1250, 1252, 1254, 1256, 1258, 1260, 1261, 1263, 1265, 1267, 1269, 1270,
+    1272, 1274, 1276, 1278, 1279, 1281, 1283, 1284, 1286, 1288, 1289, 1291,
+    1293, 1294, 1296, 1298, 1299, 1301, 1302, 1304, 1306, 1307, 1309, 1310,
+    1312, 1313, 1315, 1316, 1318, 1319, 1321, 1322, 1324, 1325, 1327, 1328,
+    1329, 1331, 1332, 1334, 1335, 1336, 1338, 1339, 1341, 1342, 1343, 1345,
+    1346, 1347, 1349, 1350, 1351, 1353, 1354, 1355, 1356, 1358, 1359, 1360,
+    1361, 1363, 1364, 1365, 1366, 1368, 1369, 1370, 1371, 1372, 1374, 1375,
+    1376, 1377, 1378, 1380, 1381, 1382, 1383, 1384, 1385, 1387, 1388, 1389,
+    1390, 1391, 1392, 1393, 1394, 1395, 1397, 1398, 1399, 1400, 1401, 1402,
+    1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1415,
+    1416, 1417, 1418, 1419
+  };
+
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function: os_pow_fix()
+ *
+ * Parameters:
+ *    [IN] base:  the base, should be between 0 and 255.
+ *    [IN] power:  this must be in 24i.8f format.
+ *
+ * Description:
+ *    This function uses the Taylor Series to approximate the power function
+ *    using fixed-point math.  See this website for the math background
+ *    http://www.efunda.com/math/taylor_series/exponential.cfm
+ *
+ *    This function was originally designed for gamma correction.  When the
+ *    base value is between 1 - 255 and the power is between 0.1 and 2, this
+ *    function will produce an approximation that is within 2% of the "real"
+ *    function.
+ *
+ * Returns:
+ *    The result in 24i.8f format
+ *
+ *----------------------------------------------------------------------------
+ */
+
+unsigned int os_pow_fix( const int base, const int power )
+{
+  /* For some reason using "const unsigned int" causes a compiler error
+   * when I use it below when I declare "result[APPROXIMATE_TERMS]".  So
+   * switched these from "const unsigned .." to #define
+   */
+  #define APPROXIMATE_TERMS     40
+#define FRACTION_BITS         8    /* num of bits for fraction */
+
+  unsigned int       result[APPROXIMATE_TERMS];
+  unsigned int       i, power_loop;
+  unsigned int       total  = 0;
+  int                ln_x   = ln_table[base];  /* ln_x is in 24i.8f format */
+
+
+  /* nothing to do if we get 0 */
+  if (0 == base) {
+    return 0;
+  } else {
+    ln_x = ln_table[base];
+  }
+
+  /* We approximate the result using APPROXIMATE_TERMS terms */
+  for (i = 0; i < APPROXIMATE_TERMS; i++)    {
+
+    result[i] = 1 << FRACTION_BITS;
+
+    /* Need to be very careful about the order in which we are multiplying
+     * multiplying and dividing because we don't want any overflow.  In
+     * addition, every time we multiply 2 fixed point numbers, we need to
+     * shift the result by FRACTION_BITS to maintain the radix point.
+     */
+    for( power_loop = 0; power_loop < i; power_loop++ )    {
+      result[i] *= ln_x;
+      result[i] /= (power_loop + 1);
+      result[i] >>=FRACTION_BITS;
+      result[i] *= power;
+      result[i] >>=FRACTION_BITS;
+
+    }
+
+    total += result[i];
+
+  }
+
+  return total;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/utils/memmap.c b/drivers/gpu/drm/emgd/emgd/utils/memmap.c
new file mode 100644
index 0000000..2ee0812
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/utils/memmap.c
@@ -0,0 +1,55 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: memmap.c
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains the XFree86 implementations of the OAL
+ *  memory.h abstractions.
+ *-----------------------------------------------------------------------------
+ */
+#include <io.h>
+
+#ifndef _OAL_LINUX_KERNEL_IO_MEMMAP_H
+#define _OAL_LINUX_KERNEL_IO_MEMMAP_H
+
+
+void * os_map_io_to_mem_nocache(
+				unsigned long base_address,
+				unsigned long size
+				)
+{
+  return ioremap(base_address, size);
+}
+
+void os_unmap_io_from_mem(
+			  void * virt_addr,
+			  unsigned long size
+			  )
+{
+  iounmap(virt_addr);
+}
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/utils/pci.c b/drivers/gpu/drm/emgd/emgd/utils/pci.c
new file mode 100644
index 0000000..969fc6d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/utils/pci.c
@@ -0,0 +1,277 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: pci.c
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains Linux kernel space PCI API for the OAL abstractions.
+ *-----------------------------------------------------------------------------
+ */
+
+#include <memory.h>
+#include <pci.h>
+#include <linux/pci.h>
+#include <io.h>
+
+#if defined(CONFIG_VGA_ARB)
+#include <linux/vgaarb.h>
+#endif
+
+
+//
+// This is our local representation of a PCI device.
+// This struct is private to this file, and exposed to calling functions
+// only through an opaque "os_pci_dev_t" handle.
+//
+typedef struct _linuxkernel_pci {
+  struct pci_dev *dev;
+  unsigned int bus;
+  unsigned int slot;
+  unsigned int func;
+}linuxkernel_pci_t;
+
+/*----------------------------------------------------------------------
+ * Function:
+ *pci_find_device_generic
+ * Parameters:
+ *unsigned short vendor,
+ *unsigned short device,
+ *os_pci_dev_t os_pci_dev
+ * Description:
+ *This function finds a PCI device by going through 255 buses, 32 devices
+ *and 8 functions and tries to match each ones vendor and device ids with
+ *the ones given to it as parameters. Stops for the first device it finds
+ *with a matching vendor and device, so it will not find multiple devices.
+ *This is _NOT_ an exported OAL
+ *function.
+ * Returns:
+ *os_pci_dev_t
+ *---------------------------------------------------------------------
+ */
+static os_pci_dev_t pci_find_device_generic(
+					    unsigned short vendor_id,
+					    unsigned short device_id,
+					    os_pci_dev_t pci_dev_handle
+					    )
+{
+  struct pci_dev *our_device; // Kernel struct for a PCI device
+  linuxkernel_pci_t *pdev; // Our struct for a PCI device.
+
+    // Locate the device, and lock it. Start search at the start of the list.
+    our_device = pci_get_device(vendor_id, device_id, NULL);
+    // If we didn't find it, return an error.
+    if (!our_device){
+      return (os_pci_dev_t)NULL;
+    }
+
+    // Get the pointer to the destination for the data.
+    // pci_dev_handle is an opaque pointer to a linuxkernel_pci_t struct
+    // If there isn't one, allocate it.
+    pdev = (linuxkernel_pci_t *)pci_dev_handle;
+    if(!pdev) {
+
+      // Caller did not supply a handle to a PCI device struct.
+      // Allocate one.
+      pdev = (linuxkernel_pci_t *)OS_ALLOC(sizeof(linuxkernel_pci_t));
+      if(!pdev) {
+	return (os_pci_dev_t)NULL;
+      }
+      // Zero the destination memory
+      memset(pdev, 0, sizeof(linuxkernel_pci_t));
+    }
+
+    // Copy over from the kernel struct to our struct.
+    // It is safe to copy a pointer to the pci_dev, since we
+    // have a lock on it.
+    pdev->dev = our_device;
+    pdev->bus = our_device->bus->number;
+    pdev->slot = PCI_SLOT(our_device->devfn);
+    pdev->func = PCI_FUNC(our_device->devfn);
+
+    return (os_pci_dev_t)pdev;
+}
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ *os_pci_find_device
+ *
+ *  Parameters:
+ *unsigned short vendor,
+ *unsigned short device,
+ *unsigned short bus,
+ *unsigned short dev,
+ *unsigned short func,
+ *os_pci_dev_t os_pci_dev
+ *
+ *  Description:
+ *  This function finds a PCI device by scanning the specified bus, dev, func
+ *and tries to match vendor and device ids with the ones given to it as
+ *parameters.
+ *
+ *  Notes: If the bus number is 0xFFFF, then the function searches for that
+ *  vendor_id, device_id pair in the whole PCI topology of the system i.e
+ *  it goes through all the buses, devices, functions in the system
+ *
+ * Returns:
+ *os_pci_dev_t
+ *---------------------------------------------------------------------
+ */
+os_pci_dev_t os_pci_find_device(
+				unsigned short vendor_id,
+				unsigned short device_id,
+				unsigned short bus,
+				unsigned short dev,
+				unsigned short func,
+				os_pci_dev_t pci_dev)
+{
+  /* TODO: Right now, Just fallback to pci_find_device_generic
+   * But we need to implement this
+   */
+  return pci_find_device_generic(vendor_id, device_id, pci_dev);
+}
+
+int os_pci_get_slot_address(
+			    os_pci_dev_t pci_dev,
+			    unsigned int *bus,
+			    unsigned int *slot,
+			    unsigned int *func)
+{
+
+  linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+  EMGD_ASSERT(pdev, "Invalid pci device", 0);
+
+  if(bus) {
+    *bus = pdev->bus;
+  }
+  if(slot) {
+    *slot = pdev->slot;
+  }
+  if(func) {
+    *func = pdev->func;
+  }
+  return 0;
+}
+
+int os_pci_read_config_8(
+			 os_pci_dev_t pci_dev,
+			 unsigned long offset,
+			 unsigned char* val
+			 )
+{
+  linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+  EMGD_ASSERT(pdev, "Invalid pci device", 0);
+  EMGD_ASSERT(val, "Invalid pointer", 0);
+  return pci_read_config_byte(pdev->dev, offset, val);
+}
+
+int os_pci_read_config_16(
+			  os_pci_dev_t pci_dev,
+			  unsigned long offset,
+			  unsigned short* val
+			  )
+{
+  linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+  EMGD_ASSERT(pdev, "Invalid pci device", 0);
+  EMGD_ASSERT(val, "Invalid pointer", 0);
+  return pci_read_config_word(pdev->dev, offset,val);
+}
+
+int os_pci_read_config_32(
+			  os_pci_dev_t pci_dev,
+			  unsigned long offset,
+			  unsigned long* val
+			  )
+{
+  linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+  EMGD_ASSERT(pdev, "Invalid pci device", 0);
+  EMGD_ASSERT(val, "Invalid pointer", 0);
+  return pci_read_config_dword(pdev->dev, offset, (u32*)val);
+}
+
+int os_pci_write_config_8(
+			  os_pci_dev_t pci_dev,
+			  unsigned long offset,
+			  unsigned char val
+			  )
+{
+  linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+  EMGD_ASSERT(pdev, "Invalid pci device", 0);
+  return pci_write_config_byte(pdev->dev, offset, val);
+}
+
+int os_pci_write_config_16(
+			   os_pci_dev_t pci_dev,
+			   unsigned long offset,
+			   unsigned short val
+			   )
+{
+  linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+  EMGD_ASSERT(pdev, "Invalid pci device", 0);
+  return pci_write_config_word(pdev->dev, offset, val);
+}
+
+int os_pci_write_config_32(
+			   os_pci_dev_t pci_dev,
+			   unsigned long offset,
+			   unsigned long val
+			   )
+{
+  linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+  EMGD_ASSERT(pdev, "Invalid pci device", 0);
+  return pci_write_config_dword(pdev->dev, offset, val);
+}
+
+int os_pci_disable_legacy_vga_decoding(
+			os_pci_dev_t pci_dev
+		)
+{
+#if defined(CONFIG_VGA_ARB)
+	linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+	EMGD_ASSERT(pdev, "Invalid pci device", 0);
+
+	vga_set_legacy_decoding(pdev->dev, VGA_RSRC_NONE);
+#else
+	/* Noop if the VGA arbiter isn't compiled into the kernel */
+#endif
+
+	return 0;
+}
+
+
+void os_pci_free_device(
+			os_pci_dev_t pci_dev
+			)
+{
+  linuxkernel_pci_t *pdev = (linuxkernel_pci_t *)pci_dev;
+
+  // Release the lock on our PCI device struct
+  pci_dev_put(pdev->dev);
+
+  // Free our local structure.
+  OS_FREE(pdev);
+
+  return;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx.c b/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx.c
new file mode 100644
index 0000000..644c3cc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx.c
@@ -0,0 +1,913 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: msvdx.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:
+ *  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);
+void 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;
+}
+
+void 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 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]);
+		}
+
+		mtx_msgs += (submit_size / sizeof(unsigned long));
+	}
+}
+
+/*
+ * 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/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_init.c b/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_init.c
new file mode 100644
index 0000000..6591224
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_init.c
@@ -0,0 +1,1516 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: msvdx_init.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:
+ *  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"
+
+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 void 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)
+
+
+
+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;
+	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){
+	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);
+
+    } 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)
+{
+	EMGD_TRACE_ENTER;
+
+	if(context_count) {
+		context_count -= 1;
+	} else {
+		EMGD_TRACE_EXIT;
+		return 1;
+	}
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+int msvdx_create_context(igd_context_t *context)
+{
+	EMGD_TRACE_ENTER;
+
+	context_count +=1;
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+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;
+			}
+
+			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/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.c b/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.c
new file mode 100644
index 0000000..1e36594
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.c
@@ -0,0 +1,583 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: msvdx_pvr.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 "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_GENERAL_MAPPING_HEAP_ID) {
+			pvr->mapping_heap_index = i;
+			break;
+		}
+	}
+
+	platform->msvdx_pvr = pvr;
+	pvr->pid = pid;
+
+
+	return 0;
+
+out_stop_kthread:
+	kthread_stop(pvr->kthread);
+out_free:
+	kfree(pvr);
+	return ret;
+}
+
+/*
+ * HHP: FIXME:
+ * This should also be called when GMM/GTT is re-initialized, i.e. when
+ * the Xorg server stops.  The PVR backed memory is invalid when this happens,
+ * so if we call this function from msvdx_driver_unload() when the module is
+ * removed, the "fw_mem_info" and "dev_mem_context" are invalid.
+ */
+void msvdx_pvr_deinit(void)
+{
+	drm_emgd_priv_t       *priv;
+	igd_context_t          *context;
+	platform_context_plb_t *platform;
+	struct msvdx_pvr_info  *pvr;
+	IMG_BOOL mem_destroyed;
+	int pid=0;
+	unsigned char *mmio;
+
+	priv     = gpDrmDevice->dev_private;
+	context  = priv->context;
+	platform = (platform_context_plb_t *)context->platform_context;
+    mmio = context->device_context.virt_mmadr;
+	pvr = platform->msvdx_pvr;
+
+    //Reset MTX before unloading firmware
+    EMGD_WRITE32(0x00000001, mmio + PSB_MSVDX_MTX_SOFT_RESET);
+
+
+	if (pvr) {
+        kthread_stop(pvr->kthread);
+		if (pvr->fw_mem_info)
+			PVRSRVFreeDeviceMemKM(pvr->sgx_cookie,
+						pvr->fw_mem_info);
+
+		PVRSRVDestroyDeviceMemContextKM(pvr->sgx_cookie,
+						pvr->dev_mem_context,
+						&mem_destroyed);
+
+	//	PVRSRVPerProcessDataDisconnect((IMG_UINT32)pvr->kthread->pid);
+        PVRSRVPerProcessDataDisconnect((IMG_UINT32)pvr->pid);
+        pid = pvr->pid;
+		kfree(pvr);
+		platform->msvdx_pvr = NULL;
+	}
+
+}
+
+PVRSRV_KERNEL_MEM_INFO *msvdx_pvr_alloc_devmem(unsigned long alloc_size,
+	const char *mame)
+{
+	drm_emgd_priv_t        *priv;
+	igd_context_t           *context;
+	platform_context_plb_t  *platform;
+	struct msvdx_pvr_info   *pvr;
+	PVRSRV_KERNEL_MEM_INFO  *mem_info;
+	PVRSRV_ERROR err;
+
+	priv     = gpDrmDevice->dev_private;
+	context  = priv->context;
+	platform = (platform_context_plb_t *)context->platform_context;
+
+	pvr = platform->msvdx_pvr;
+	if (!pvr)
+		return NULL;
+
+	/* Is PVRSRV_MEM_CACHE_CONSISTENT needed in the allocation flags? */
+	err = PVRSRVAllocDeviceMemKM(pvr->sgx_cookie, pvr->per_proc,
+			pvr->heap_info[pvr->mapping_heap_index].hDevMemHeap,
+			PVRSRV_MEM_READ | PVRSRV_MEM_WRITE,
+			alloc_size, 0, &mem_info, name);
+	if (err != PVRSRV_OK) {
+		printk(KERN_ERR "[EMGD] MSVDX: PVRSRVAllocDeviceMemKM failed, "
+			"error=%u\n", (unsigned int)err);
+		return NULL;
+	}
+
+	return mem_info;
+}
+
+static PVRSRV_ERROR DevInitMSVDXPart1(IMG_VOID *pvDeviceNode)
+{
+    /*
+	PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+	PVRSRV_ERROR eError;
+	PVRSRV_DEV_POWER_STATE eDefaultPowerState;
+    */
+
+	/* register power operation function */
+	/* FIXME: this should be in part2 init function, but
+	 * currently here only OSPM needs IMG device... */
+    /*
+	eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
+	eError = PVRSRVRegisterPowerDevice(psDeviceNode->sDevId.ui32DeviceIndex,
+					   MSVDXPrePowerState,
+					   MSVDXPostPowerState,
+					   MSVDXPreClockSpeedChange,
+					   MSVDXPostClockSpeedChange,
+					   (IMG_HANDLE)psDeviceNode,
+					   PVRSRV_DEV_POWER_STATE_ON,
+					   eDefaultPowerState);
+	if (eError != PVRSRV_OK) {
+		PVR_DPF((PVR_DBG_ERROR, "DevInitMSVDXPart1: failed to "
+			 "register device with power manager"));
+		return eError;
+	}
+    */
+
+	return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR DevDeInitMSVDX(IMG_VOID *pvDeviceNode)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+	PVRSRV_ERROR eError;
+
+	/* should deinit all resource */
+
+	eError = PVRSRVRemovePowerDevice(psDeviceNode->sDevId.ui32DeviceIndex);
+	if (eError != PVRSRV_OK)
+		return eError;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	/* version check */
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	psDeviceNode->sDevId.eDeviceType	= PVRSRV_DEVICE_TYPE_MSVDX;
+	psDeviceNode->sDevId.eDeviceClass	= PVRSRV_DEVICE_CLASS_VIDEO;
+
+	psDeviceNode->pfnInitDevice		= DevInitMSVDXPart1;
+	psDeviceNode->pfnDeInitDevice		= DevDeInitMSVDX;
+
+	psDeviceNode->pfnInitDeviceCompatCheck	= MSVDXDevInitCompatCheck;
+
+	psDeviceNode->pfnDeviceISR = msvdx_mtx_isr;
+	psDeviceNode->pvISRData = (IMG_VOID *)gpDrmDevice;
+
+	return PVRSRV_OK;
+}
+
+/*
+PVRSRV_ERROR MSVDXPrePowerState(IMG_HANDLE hDevHandle,
+				 PVRSRV_DEV_POWER_STATE	eNewPowerState,
+				 PVRSRV_DEV_POWER_STATE	eCurrentPowerState)
+{
+	// ask for a change not power on
+	if ((eNewPowerState != eCurrentPowerState) &&
+	    (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON)) {
+		struct drm_psb_private *dev_priv = gpDrmDevice->dev_private;
+		struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+		MSVDX_NEW_PMSTATE(gpDrmDevice, msvdx_priv, PSB_PMSTATE_POWERDOWN);
+
+		// context save
+		psb_msvdx_save_context(gpDrmDevice);
+
+		// internally close the device //
+
+		// ask for power off //
+		if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF) {
+			// here will deinitialize the driver if needed //
+		} else {
+			PVR_DPF((PVR_DBG_MESSAGE,
+				"%s no action for transform from %d to %d",
+				 __func__,
+				eCurrentPowerState,
+				eNewPowerState));
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXPostPowerState(IMG_HANDLE hDevHandle,
+				 PVRSRV_DEV_POWER_STATE	eNewPowerState,
+				 PVRSRV_DEV_POWER_STATE	eCurrentPowerState)
+{
+	// if ask for change & current status is not on //
+	if ((eNewPowerState != eCurrentPowerState) &&
+	    (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON)) {
+		// internally open device //
+		struct drm_psb_private *dev_priv = gpDrmDevice->dev_private;
+		struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+		MSVDX_NEW_PMSTATE(gpDrmDevice, msvdx_priv, PSB_PMSTATE_POWERUP);
+
+		// context restore //
+		psb_msvdx_restore_context(gpDrmDevice);
+
+		if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF) {
+			// here will initialize the driver if needed //
+		} else {
+			PVR_DPF((PVR_DBG_MESSAGE,
+				"%s no action for transform from %d to %d",
+				 __func__,
+				eCurrentPowerState,
+				eNewPowerState));
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXPreClockSpeedChange(IMG_HANDLE hDevHandle,
+				      IMG_BOOL bIdleDevice,
+				      PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXPostClockSpeedChange(IMG_HANDLE hDevHandle,
+				      IMG_BOOL bIdleDevice,
+				      PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+	return PVRSRV_OK;
+}
+*/
diff --git a/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.h b/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.h
new file mode 100644
index 0000000..070c935
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/msvdx/msvdx_pvr.h
@@ -0,0 +1,78 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: msvdx_pvr.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef MSVDX_POWER_H_
+#define MSVDX_POWER_H_
+#include <linux/sched.h>
+#include "services_headers.h"
+#include "sysconfig.h"
+
+extern struct drm_device *gpDrmDevice;
+
+struct msvdx_pvr_info {
+	/* HHP: FIXME: review if a mutex lock is needed here */
+	IMG_HANDLE                sgx_cookie;
+	IMG_HANDLE                dev_mem_context;
+	PVRSRV_PER_PROCESS_DATA  *per_proc;
+	PVRSRV_HEAP_INFO          heap_info[PVRSRV_MAX_CLIENT_HEAPS];
+	IMG_BOOL                  heap_shared[PVRSRV_MAX_CLIENT_HEAPS];
+	IMG_UINT32                heap_count;
+	/* index of SGX_GENERAL_MAPPING_HEAP_ID in heap_info[] */
+	int                       mapping_heap_index;
+	PVRSRV_KERNEL_MEM_INFO   *fw_mem_info;
+	/* Needed for PVR per process data */
+	struct task_struct       *kthread;
+	IMG_UINT32                pid;
+};
+/* function define */
+PVRSRV_ERROR MSVDXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+PVRSRV_ERROR MSVDXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+/* power function define */
+PVRSRV_ERROR MSVDXPrePowerState(IMG_HANDLE	hDevHandle,
+			PVRSRV_DEV_POWER_STATE	eNewPowerState,
+			PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+PVRSRV_ERROR MSVDXPostPowerState(IMG_HANDLE	hDevHandle,
+			 PVRSRV_DEV_POWER_STATE	eNewPowerState,
+			 PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+PVRSRV_ERROR MSVDXPreClockSpeedChange(IMG_HANDLE	hDevHandle,
+			      IMG_BOOL			bIdleDevice,
+			      PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+PVRSRV_ERROR MSVDXPostClockSpeedChange(IMG_HANDLE	hDevHandle,
+			       IMG_BOOL			bIdleDevice,
+			       PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+PVRSRV_ERROR MSVDXInitOSPM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+extern int  msvdx_pvr_init(void);
+extern void msvdx_pvr_deinit(void);
+extern PVRSRV_KERNEL_MEM_INFO *msvdx_pvr_alloc_devmem(
+	unsigned long alloc_size, const char *name);
+#endif /* !MSVDX_POWER_H_ */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/igd_ovl.c b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/igd_ovl.c
new file mode 100644
index 0000000..adf31a6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/igd_ovl.c
@@ -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/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/micro_ovl.c b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/micro_ovl.c
new file mode 100644
index 0000000..7a15220
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/micro_ovl.c
@@ -0,0 +1,165 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: micro_ovl.c
+ * $Revision: 1.13 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.overlay
+
+#include <context.h>
+#include <memory.h>
+#include <dsp.h>
+#include <io.h>
+
+#include <igd_mode.h>
+#include <igd_gmm.h>
+//#include <igd_ovl.h>
+#include <igd_pwr.h>
+#include <igd_render.h>
+#include <igd_blend.h>
+
+#include <general.h>
+#include <mode_access.h>
+#include <dispatch.h>
+#include <intelpci.h>
+
+#include "ovl_dispatch.h"
+#include "ovl_virt.h"
+
+/*
+ * TODO: If there is micro overlay for device dependent layer
+ * modify extern below to the correct micro device dispatch
+ * Only two micro overlay existing is for Plb and Ctg
+ */
+
+extern ovl_dispatch_t ovl_micro_dispatch_plb[];
+
+static dispatch_table_t ovl_micro_dispatch_list[] = {
+/*
+ * TODO: Fix this.
+ *  * This table would point the micro dispatch tables.
+ *  For now, other than Plb ,refer the micro dispatch
+ *  to the original table
+ * */
+
+#ifdef CONFIG_PLB
+	{PCI_DEVICE_ID_VGA_PLB, &ovl_micro_dispatch_plb},
+#endif
+#ifdef CONFIG_TNC
+	{PCI_DEVICE_ID_VGA_TNC, &ovl_micro_dispatch_plb},
+#endif
+	{0, NULL}
+};
+extern int ovl_full_init(igd_context_t *context, igd_param_t *params,ovl_context_t *ovl_context);
+
+#ifndef CONFIG_MICRO_OVERLAY
+#define OVL_FULL_INIT(a, b, c) ovl_full_init(a, b, c)
+#else
+#define OVL_FULL_INIT(a, b, c) 1
+#endif
+
+extern ovl_context_t ovl_context[1];
+static int igd_micro_alter_ovl(igd_display_h display_h,
+	igd_appcontext_h     appcontext_h,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	igd_ovl_info_t      *ovl_info,
+	unsigned int         flags)
+{
+	igd_display_context_t *display =
+		(igd_display_context_t *)display_h;
+	ovl_dispatch_t    *ovl_dispatch =
+		(ovl_dispatch_t *)ovl_context->dispatch;
+
+	igd_display_context_t *ovl_display;
+
+	int ret = 0;
+
+	EMGD_TRACE_ENTER;
+
+	ovl_display = display;
+
+	/* Call family dependent overlay function to alter the overlay. */
+	ret = ovl_dispatch->alter_ovl(
+				ovl_display, src_surf, src_rect,
+				dest_rect, ovl_info, flags);
+
+	if (ret != IGD_SUCCESS) {
+		EMGD_ERROR("Error micro alter overlay\n");
+		/* Turn the overlay off when there is an error */
+		ovl_dispatch->alter_ovl(ovl_display,
+					NULL, NULL, NULL, NULL, IGD_OVL_ALTER_OFF);
+	}
+
+	EMGD_TRACE_EXIT;
+	return ret;
+}
+
+int _overlay_init(igd_context_t *context, igd_param_t *params)
+{
+
+	EMGD_TRACE_ENTER;
+
+	/* Ensure the device context pointer is valid */
+	if(!context){
+		EMGD_ERROR_EXIT("Error: Null context");
+		return -IGD_ERROR_INVAL;
+	}
+
+	/* Clear the allocated memory for overlay context */
+	OS_MEMSET((void *)ovl_context, 0, sizeof(ovl_context_t));
+
+	/* Get overlay's dispatch table */
+	ovl_context->dispatch = (ovl_dispatch_t (*)[])dispatch_acquire(context,
+		ovl_micro_dispatch_list);
+	if(!ovl_context->dispatch) {
+		EMGD_ERROR_EXIT("Error: Unsupported Device");
+		return -IGD_ERROR_NODEV;
+	}
+
+
+	/* Hook up the IGD dispatch table entries for overlay
+	 * Alter has a common function, query can call the family function
+	 * directly */
+	context->dispatch.alter_ovl = igd_micro_alter_ovl;
+	context->dispatch.query_ovl = NULL;
+	context->dispatch.query_max_size_ovl = NULL;
+	context->mod_dispatch.overlay_shutdown = NULL;
+
+	if (OVL_FULL_INIT(context, params, ovl_context)) {
+		/*
+		 * Even if full init failed we can still use the micro-gmm
+		 */
+		EMGD_DEBUG("Full overlay did not initialize, using micro-overlay");
+
+	}
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_coeff.c b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_coeff.c
new file mode 100644
index 0000000..fc08f0e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_coeff.c
@@ -0,0 +1,1127 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_coeff.c
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file calculates the coefficient values used by the various
+ *  platform families.
+ *-----------------------------------------------------------------------------
+ */
+
+#include <general.h>
+#include <memory.h>
+
+#include "ovl_coeff.h"
+
+/*****************************************************************
+ *                                                               *
+ *        HARDCODED QUARTER SINE WAVE TABLES                     *
+ *        4096 unsigned shorts MSB is integer                    *
+ *        and 15 LSB's are after the radix                       *
+ *                                                               *
+ *****************************************************************/
+static unsigned short wave_table[4096] = {
+	/* 16 bit value - all 16 bits are fp only */
+	0x0,  0x19,  0x32,  0x4b,  0x65,  0x7e,  0x97,  0xb0,  0xc9,  0xe2,
+	0xfb,  0x114,  0x12e,  0x147,  0x160,  0x179,  0x192,  0x1ab,  0x1c4,  0x1de,
+	0x1f7,  0x210,  0x229,  0x242,  0x25b,  0x274,  0x28d,  0x2a7,  0x2c0,  0x2d9,
+	0x2f2,  0x30b,  0x324,  0x33d,  0x356,  0x370,  0x389,  0x3a2,  0x3bb,  0x3d4,
+	0x3ed,  0x406,  0x420,  0x439,  0x452,  0x46b,  0x484,  0x49d,  0x4b6,  0x4cf,
+	0x4e9,  0x502,  0x51b,  0x534,  0x54d,  0x566,  0x57f,  0x598,  0x5b2,  0x5cb,
+	0x5e4,  0x5fd,  0x616,  0x62f,  0x648,  0x661,  0x67b,  0x694,  0x6ad,  0x6c6,
+	0x6df,  0x6f8,  0x711,  0x72a,  0x744,  0x75d,  0x776,  0x78f,  0x7a8,  0x7c1,
+	0x7da,  0x7f3,  0x80d,  0x826,  0x83f,  0x858,  0x871,  0x88a,  0x8a3,  0x8bc,
+	0x8d5,  0x8ef,  0x908,  0x921,  0x93a,  0x953,  0x96c,  0x985,  0x99e,  0x9b8,
+	0x9d1,  0x9ea,  0xa03,  0xa1c,  0xa35,  0xa4e,  0xa67,  0xa80,  0xa9a,  0xab3,
+	0xacc,  0xae5,  0xafe,  0xb17,  0xb30,  0xb49,  0xb62,  0xb7c,  0xb95,  0xbae,
+	0xbc7,  0xbe0,  0xbf9,  0xc12,  0xc2b,  0xc44,  0xc5d,  0xc77,  0xc90,  0xca9,
+	0xcc2,  0xcdb,  0xcf4,  0xd0d,  0xd26,  0xd3f,  0xd59,  0xd72,  0xd8b,  0xda4,
+	0xdbd,  0xdd6,  0xdef,  0xe08,  0xe21,  0xe3a,  0xe53,  0xe6d,  0xe86,  0xe9f,
+	0xeb8,  0xed1,  0xeea,  0xf03,  0xf1c,  0xf35,  0xf4e,  0xf67,  0xf81,  0xf9a,
+	0xfb3,  0xfcc,  0xfe5,  0xffe,  0x1017,  0x1030,  0x1049,  0x1062,  0x107b,  0x1094,
+	0x10ae,  0x10c7,  0x10e0,  0x10f9,  0x1112,  0x112b,  0x1144,  0x115d,  0x1176,  0x118f,
+	0x11a8,  0x11c1,  0x11da,  0x11f4,  0x120d,  0x1226,  0x123f,  0x1258,  0x1271,  0x128a,
+	0x12a3,  0x12bc,  0x12d5,  0x12ee,  0x1307,  0x1320,  0x1339,  0x1352,  0x136c,  0x1385,
+	0x139e,  0x13b7,  0x13d0,  0x13e9,  0x1402,  0x141b,  0x1434,  0x144d,  0x1466,  0x147f,
+	0x1498,  0x14b1,  0x14ca,  0x14e3,  0x14fc,  0x1515,  0x152e,  0x1548,  0x1561,  0x157a,
+	0x1593,  0x15ac,  0x15c5,  0x15de,  0x15f7,  0x1610,  0x1629,  0x1642,  0x165b,  0x1674,
+	0x168d,  0x16a6,  0x16bf,  0x16d8,  0x16f1,  0x170a,  0x1723,  0x173c,  0x1755,  0x176e,
+	0x1787,  0x17a0,  0x17b9,  0x17d2,  0x17eb,  0x1804,  0x181d,  0x1837,  0x1850,  0x1869,
+	0x1882,  0x189b,  0x18b4,  0x18cd,  0x18e6,  0x18ff,  0x1918,  0x1931,  0x194a,  0x1963,
+	0x197c,  0x1995,  0x19ae,  0x19c7,  0x19e0,  0x19f9,  0x1a12,  0x1a2b,  0x1a44,  0x1a5d,
+	0x1a76,  0x1a8f,  0x1aa8,  0x1ac1,  0x1ada,  0x1af3,  0x1b0c,  0x1b25,  0x1b3e,  0x1b57,
+	0x1b70,  0x1b89,  0x1ba2,  0x1bbb,  0x1bd4,  0x1bed,  0x1c06,  0x1c1f,  0x1c38,  0x1c51,
+	0x1c69,  0x1c82,  0x1c9b,  0x1cb4,  0x1ccd,  0x1ce6,  0x1cff,  0x1d18,  0x1d31,  0x1d4a,
+	0x1d63,  0x1d7c,  0x1d95,  0x1dae,  0x1dc7,  0x1de0,  0x1df9,  0x1e12,  0x1e2b,  0x1e44,
+	0x1e5d,  0x1e76,  0x1e8f,  0x1ea8,  0x1ec1,  0x1eda,  0x1ef3,  0x1f0b,  0x1f24,  0x1f3d,
+	0x1f56,  0x1f6f,  0x1f88,  0x1fa1,  0x1fba,  0x1fd3,  0x1fec,  0x2005,  0x201e,  0x2037,
+	0x2050,  0x2069,  0x2082,  0x209a,  0x20b3,  0x20cc,  0x20e5,  0x20fe,  0x2117,  0x2130,
+	0x2149,  0x2162,  0x217b,  0x2194,  0x21ad,  0x21c6,  0x21de,  0x21f7,  0x2210,  0x2229,
+	0x2242,  0x225b,  0x2274,  0x228d,  0x22a6,  0x22bf,  0x22d7,  0x22f0,  0x2309,  0x2322,
+	0x233b,  0x2354,  0x236d,  0x2386,  0x239f,  0x23b8,  0x23d0,  0x23e9,  0x2402,  0x241b,
+	0x2434,  0x244d,  0x2466,  0x247f,  0x2497,  0x24b0,  0x24c9,  0x24e2,  0x24fb,  0x2514,
+	0x252d,  0x2546,  0x255e,  0x2577,  0x2590,  0x25a9,  0x25c2,  0x25db,  0x25f4,  0x260c,
+	0x2625,  0x263e,  0x2657,  0x2670,  0x2689,  0x26a2,  0x26ba,  0x26d3,  0x26ec,  0x2705,
+	0x271e,  0x2737,  0x274f,  0x2768,  0x2781,  0x279a,  0x27b3,  0x27cc,  0x27e4,  0x27fd,
+	0x2816,  0x282f,  0x2848,  0x2860,  0x2879,  0x2892,  0x28ab,  0x28c4,  0x28dd,  0x28f5,
+	0x290e,  0x2927,  0x2940,  0x2959,  0x2971,  0x298a,  0x29a3,  0x29bc,  0x29d5,  0x29ed,
+	0x2a06,  0x2a1f,  0x2a38,  0x2a51,  0x2a69,  0x2a82,  0x2a9b,  0x2ab4,  0x2acc,  0x2ae5,
+	0x2afe,  0x2b17,  0x2b30,  0x2b48,  0x2b61,  0x2b7a,  0x2b93,  0x2bab,  0x2bc4,  0x2bdd,
+	0x2bf6,  0x2c0e,  0x2c27,  0x2c40,  0x2c59,  0x2c71,  0x2c8a,  0x2ca3,  0x2cbc,  0x2cd4,
+	0x2ced,  0x2d06,  0x2d1f,  0x2d37,  0x2d50,  0x2d69,  0x2d82,  0x2d9a,  0x2db3,  0x2dcc,
+	0x2de5,  0x2dfd,  0x2e16,  0x2e2f,  0x2e47,  0x2e60,  0x2e79,  0x2e92,  0x2eaa,  0x2ec3,
+	0x2edc,  0x2ef4,  0x2f0d,  0x2f26,  0x2f3f,  0x2f57,  0x2f70,  0x2f89,  0x2fa1,  0x2fba,
+	0x2fd3,  0x2feb,  0x3004,  0x301d,  0x3035,  0x304e,  0x3067,  0x307f,  0x3098,  0x30b1,
+	0x30ca,  0x30e2,  0x30fb,  0x3114,  0x312c,  0x3145,  0x315e,  0x3176,  0x318f,  0x31a7,
+	0x31c0,  0x31d9,  0x31f1,  0x320a,  0x3223,  0x323b,  0x3254,  0x326d,  0x3285,  0x329e,
+	0x32b7,  0x32cf,  0x32e8,  0x3300,  0x3319,  0x3332,  0x334a,  0x3363,  0x337c,  0x3394,
+	0x33ad,  0x33c5,  0x33de,  0x33f7,  0x340f,  0x3428,  0x3440,  0x3459,  0x3472,  0x348a,
+	0x34a3,  0x34bb,  0x34d4,  0x34ed,  0x3505,  0x351e,  0x3536,  0x354f,  0x3568,  0x3580,
+	0x3599,  0x35b1,  0x35ca,  0x35e2,  0x35fb,  0x3614,  0x362c,  0x3645,  0x365d,  0x3676,
+	0x368e,  0x36a7,  0x36c0,  0x36d8,  0x36f1,  0x3709,  0x3722,  0x373a,  0x3753,  0x376b,
+	0x3784,  0x379c,  0x37b5,  0x37cd,  0x37e6,  0x37fe,  0x3817,  0x3830,  0x3848,  0x3861,
+	0x3879,  0x3892,  0x38aa,  0x38c3,  0x38db,  0x38f4,  0x390c,  0x3925,  0x393d,  0x3956,
+	0x396e,  0x3987,  0x399f,  0x39b8,  0x39d0,  0x39e9,  0x3a01,  0x3a1a,  0x3a32,  0x3a4a,
+	0x3a63,  0x3a7b,  0x3a94,  0x3aac,  0x3ac5,  0x3add,  0x3af6,  0x3b0e,  0x3b27,  0x3b3f,
+	0x3b58,  0x3b70,  0x3b88,  0x3ba1,  0x3bb9,  0x3bd2,  0x3bea,  0x3c03,  0x3c1b,  0x3c33,
+	0x3c4c,  0x3c64,  0x3c7d,  0x3c95,  0x3cae,  0x3cc6,  0x3cde,  0x3cf7,  0x3d0f,  0x3d28,
+	0x3d40,  0x3d58,  0x3d71,  0x3d89,  0x3da2,  0x3dba,  0x3dd2,  0x3deb,  0x3e03,  0x3e1c,
+	0x3e34,  0x3e4c,  0x3e65,  0x3e7d,  0x3e95,  0x3eae,  0x3ec6,  0x3edf,  0x3ef7,  0x3f0f,
+	0x3f28,  0x3f40,  0x3f58,  0x3f71,  0x3f89,  0x3fa1,  0x3fba,  0x3fd2,  0x3fea,  0x4003,
+	0x401b,  0x4033,  0x404c,  0x4064,  0x407c,  0x4095,  0x40ad,  0x40c5,  0x40de,  0x40f6,
+	0x410e,  0x4127,  0x413f,  0x4157,  0x416f,  0x4188,  0x41a0,  0x41b8,  0x41d1,  0x41e9,
+	0x4201,  0x421a,  0x4232,  0x424a,  0x4262,  0x427b,  0x4293,  0x42ab,  0x42c3,  0x42dc,
+	0x42f4,  0x430c,  0x4324,  0x433d,  0x4355,  0x436d,  0x4385,  0x439e,  0x43b6,  0x43ce,
+	0x43e6,  0x43ff,  0x4417,  0x442f,  0x4447,  0x4460,  0x4478,  0x4490,  0x44a8,  0x44c0,
+	0x44d9,  0x44f1,  0x4509,  0x4521,  0x4539,  0x4552,  0x456a,  0x4582,  0x459a,  0x45b2,
+	0x45cb,  0x45e3,  0x45fb,  0x4613,  0x462b,  0x4643,  0x465c,  0x4674,  0x468c,  0x46a4,
+	0x46bc,  0x46d4,  0x46ec,  0x4705,  0x471d,  0x4735,  0x474d,  0x4765,  0x477d,  0x4795,
+	0x47ae,  0x47c6,  0x47de,  0x47f6,  0x480e,  0x4826,  0x483e,  0x4856,  0x486f,  0x4887,
+	0x489f,  0x48b7,  0x48cf,  0x48e7,  0x48ff,  0x4917,  0x492f,  0x4947,  0x495f,  0x4978,
+	0x4990,  0x49a8,  0x49c0,  0x49d8,  0x49f0,  0x4a08,  0x4a20,  0x4a38,  0x4a50,  0x4a68,
+	0x4a80,  0x4a98,  0x4ab0,  0x4ac8,  0x4ae0,  0x4af8,  0x4b10,  0x4b28,  0x4b40,  0x4b58,
+	0x4b71,  0x4b89,  0x4ba1,  0x4bb9,  0x4bd1,  0x4be9,  0x4c01,  0x4c19,  0x4c31,  0x4c49,
+	0x4c61,  0x4c79,  0x4c90,  0x4ca8,  0x4cc0,  0x4cd8,  0x4cf0,  0x4d08,  0x4d20,  0x4d38,
+	0x4d50,  0x4d68,  0x4d80,  0x4d98,  0x4db0,  0x4dc8,  0x4de0,  0x4df8,  0x4e10,  0x4e28,
+	0x4e40,  0x4e58,  0x4e70,  0x4e87,  0x4e9f,  0x4eb7,  0x4ecf,  0x4ee7,  0x4eff,  0x4f17,
+	0x4f2f,  0x4f47,  0x4f5f,  0x4f77,  0x4f8e,  0x4fa6,  0x4fbe,  0x4fd6,  0x4fee,  0x5006,
+	0x501e,  0x5036,  0x504d,  0x5065,  0x507d,  0x5095,  0x50ad,  0x50c5,  0x50dd,  0x50f4,
+	0x510c,  0x5124,  0x513c,  0x5154,  0x516c,  0x5183,  0x519b,  0x51b3,  0x51cb,  0x51e3,
+	0x51fb,  0x5212,  0x522a,  0x5242,  0x525a,  0x5272,  0x5289,  0x52a1,  0x52b9,  0x52d1,
+	0x52e8,  0x5300,  0x5318,  0x5330,  0x5348,  0x535f,  0x5377,  0x538f,  0x53a7,  0x53be,
+	0x53d6,  0x53ee,  0x5406,  0x541d,  0x5435,  0x544d,  0x5464,  0x547c,  0x5494,  0x54ac,
+	0x54c3,  0x54db,  0x54f3,  0x550b,  0x5522,  0x553a,  0x5552,  0x5569,  0x5581,  0x5599,
+	0x55b0,  0x55c8,  0x55e0,  0x55f7,  0x560f,  0x5627,  0x563e,  0x5656,  0x566e,  0x5685,
+	0x569d,  0x56b5,  0x56cc,  0x56e4,  0x56fc,  0x5713,  0x572b,  0x5743,  0x575a,  0x5772,
+	0x5789,  0x57a1,  0x57b9,  0x57d0,  0x57e8,  0x57ff,  0x5817,  0x582f,  0x5846,  0x585e,
+	0x5875,  0x588d,  0x58a5,  0x58bc,  0x58d4,  0x58eb,  0x5903,  0x591a,  0x5932,  0x594a,
+	0x5961,  0x5979,  0x5990,  0x59a8,  0x59bf,  0x59d7,  0x59ee,  0x5a06,  0x5a1d,  0x5a35,
+	0x5a4c,  0x5a64,  0x5a7b,  0x5a93,  0x5aaa,  0x5ac2,  0x5ad9,  0x5af1,  0x5b08,  0x5b20,
+	0x5b37,  0x5b4f,  0x5b66,  0x5b7e,  0x5b95,  0x5bad,  0x5bc4,  0x5bdc,  0x5bf3,  0x5c0b,
+	0x5c22,  0x5c3a,  0x5c51,  0x5c68,  0x5c80,  0x5c97,  0x5caf,  0x5cc6,  0x5cde,  0x5cf5,
+	0x5d0c,  0x5d24,  0x5d3b,  0x5d53,  0x5d6a,  0x5d81,  0x5d99,  0x5db0,  0x5dc8,  0x5ddf,
+	0x5df6,  0x5e0e,  0x5e25,  0x5e3c,  0x5e54,  0x5e6b,  0x5e83,  0x5e9a,  0x5eb1,  0x5ec9,
+	0x5ee0,  0x5ef7,  0x5f0f,  0x5f26,  0x5f3d,  0x5f55,  0x5f6c,  0x5f83,  0x5f9b,  0x5fb2,
+	0x5fc9,  0x5fe1,  0x5ff8,  0x600f,  0x6026,  0x603e,  0x6055,  0x606c,  0x6084,  0x609b,
+	0x60b2,  0x60c9,  0x60e1,  0x60f8,  0x610f,  0x6126,  0x613e,  0x6155,  0x616c,  0x6183,
+	0x619b,  0x61b2,  0x61c9,  0x61e0,  0x61f8,  0x620f,  0x6226,  0x623d,  0x6254,  0x626c,
+	0x6283,  0x629a,  0x62b1,  0x62c8,  0x62e0,  0x62f7,  0x630e,  0x6325,  0x633c,  0x6353,
+	0x636b,  0x6382,  0x6399,  0x63b0,  0x63c7,  0x63de,  0x63f5,  0x640d,  0x6424,  0x643b,
+	0x6452,  0x6469,  0x6480,  0x6497,  0x64ae,  0x64c6,  0x64dd,  0x64f4,  0x650b,  0x6522,
+	0x6539,  0x6550,  0x6567,  0x657e,  0x6595,  0x65ac,  0x65c3,  0x65db,  0x65f2,  0x6609,
+	0x6620,  0x6637,  0x664e,  0x6665,  0x667c,  0x6693,  0x66aa,  0x66c1,  0x66d8,  0x66ef,
+	0x6706,  0x671d,  0x6734,  0x674b,  0x6762,  0x6779,  0x6790,  0x67a7,  0x67be,  0x67d5,
+	0x67ec,  0x6803,  0x681a,  0x6831,  0x6848,  0x685f,  0x6876,  0x688d,  0x68a3,  0x68ba,
+	0x68d1,  0x68e8,  0x68ff,  0x6916,  0x692d,  0x6944,  0x695b,  0x6972,  0x6989,  0x69a0,
+	0x69b6,  0x69cd,  0x69e4,  0x69fb,  0x6a12,  0x6a29,  0x6a40,  0x6a57,  0x6a6d,  0x6a84,
+	0x6a9b,  0x6ab2,  0x6ac9,  0x6ae0,  0x6af6,  0x6b0d,  0x6b24,  0x6b3b,  0x6b52,  0x6b69,
+	0x6b7f,  0x6b96,  0x6bad,  0x6bc4,  0x6bdb,  0x6bf1,  0x6c08,  0x6c1f,  0x6c36,  0x6c4d,
+	0x6c63,  0x6c7a,  0x6c91,  0x6ca8,  0x6cbe,  0x6cd5,  0x6cec,  0x6d03,  0x6d19,  0x6d30,
+	0x6d47,  0x6d5e,  0x6d74,  0x6d8b,  0x6da2,  0x6db8,  0x6dcf,  0x6de6,  0x6dfc,  0x6e13,
+	0x6e2a,  0x6e41,  0x6e57,  0x6e6e,  0x6e85,  0x6e9b,  0x6eb2,  0x6ec9,  0x6edf,  0x6ef6,
+	0x6f0d,  0x6f23,  0x6f3a,  0x6f50,  0x6f67,  0x6f7e,  0x6f94,  0x6fab,  0x6fc2,  0x6fd8,
+	0x6fef,  0x7005,  0x701c,  0x7033,  0x7049,  0x7060,  0x7076,  0x708d,  0x70a3,  0x70ba,
+	0x70d1,  0x70e7,  0x70fe,  0x7114,  0x712b,  0x7141,  0x7158,  0x716e,  0x7185,  0x719b,
+	0x71b2,  0x71c9,  0x71df,  0x71f6,  0x720c,  0x7223,  0x7239,  0x7250,  0x7266,  0x727c,
+	0x7293,  0x72a9,  0x72c0,  0x72d6,  0x72ed,  0x7303,  0x731a,  0x7330,  0x7347,  0x735d,
+	0x7373,  0x738a,  0x73a0,  0x73b7,  0x73cd,  0x73e4,  0x73fa,  0x7410,  0x7427,  0x743d,
+	0x7454,  0x746a,  0x7480,  0x7497,  0x74ad,  0x74c3,  0x74da,  0x74f0,  0x7507,  0x751d,
+	0x7533,  0x754a,  0x7560,  0x7576,  0x758d,  0x75a3,  0x75b9,  0x75d0,  0x75e6,  0x75fc,
+	0x7612,  0x7629,  0x763f,  0x7655,  0x766c,  0x7682,  0x7698,  0x76ae,  0x76c5,  0x76db,
+	0x76f1,  0x7708,  0x771e,  0x7734,  0x774a,  0x7760,  0x7777,  0x778d,  0x77a3,  0x77b9,
+	0x77d0,  0x77e6,  0x77fc,  0x7812,  0x7828,  0x783f,  0x7855,  0x786b,  0x7881,  0x7897,
+	0x78ad,  0x78c4,  0x78da,  0x78f0,  0x7906,  0x791c,  0x7932,  0x7949,  0x795f,  0x7975,
+	0x798b,  0x79a1,  0x79b7,  0x79cd,  0x79e3,  0x79f9,  0x7a10,  0x7a26,  0x7a3c,  0x7a52,
+	0x7a68,  0x7a7e,  0x7a94,  0x7aaa,  0x7ac0,  0x7ad6,  0x7aec,  0x7b02,  0x7b18,  0x7b2e,
+	0x7b44,  0x7b5a,  0x7b70,  0x7b86,  0x7b9c,  0x7bb2,  0x7bc8,  0x7bde,  0x7bf4,  0x7c0a,
+	0x7c20,  0x7c36,  0x7c4c,  0x7c62,  0x7c78,  0x7c8e,  0x7ca4,  0x7cba,  0x7cd0,  0x7ce6,
+	0x7cfc,  0x7d12,  0x7d28,  0x7d3e,  0x7d54,  0x7d6a,  0x7d7f,  0x7d95,  0x7dab,  0x7dc1,
+	0x7dd7,  0x7ded,  0x7e03,  0x7e19,  0x7e2f,  0x7e44,  0x7e5a,  0x7e70,  0x7e86,  0x7e9c,
+	0x7eb2,  0x7ec8,  0x7edd,  0x7ef3,  0x7f09,  0x7f1f,  0x7f35,  0x7f4a,  0x7f60,  0x7f76,
+	0x7f8c,  0x7fa2,  0x7fb7,  0x7fcd,  0x7fe3,  0x7ff9,  0x800f,  0x8024,  0x803a,  0x8050,
+	0x8066,  0x807b,  0x8091,  0x80a7,  0x80bc,  0x80d2,  0x80e8,  0x80fe,  0x8113,  0x8129,
+	0x813f,  0x8154,  0x816a,  0x8180,  0x8195,  0x81ab,  0x81c1,  0x81d6,  0x81ec,  0x8202,
+	0x8217,  0x822d,  0x8243,  0x8258,  0x826e,  0x8284,  0x8299,  0x82af,  0x82c4,  0x82da,
+	0x82f0,  0x8305,  0x831b,  0x8330,  0x8346,  0x835c,  0x8371,  0x8387,  0x839c,  0x83b2,
+	0x83c7,  0x83dd,  0x83f2,  0x8408,  0x841d,  0x8433,  0x8449,  0x845e,  0x8474,  0x8489,
+	0x849f,  0x84b4,  0x84ca,  0x84df,  0x84f5,  0x850a,  0x851f,  0x8535,  0x854a,  0x8560,
+	0x8575,  0x858b,  0x85a0,  0x85b6,  0x85cb,  0x85e0,  0x85f6,  0x860b,  0x8621,  0x8636,
+	0x864c,  0x8661,  0x8676,  0x868c,  0x86a1,  0x86b6,  0x86cc,  0x86e1,  0x86f7,  0x870c,
+	0x8721,  0x8737,  0x874c,  0x8761,  0x8777,  0x878c,  0x87a1,  0x87b7,  0x87cc,  0x87e1,
+	0x87f6,  0x880c,  0x8821,  0x8836,  0x884c,  0x8861,  0x8876,  0x888b,  0x88a1,  0x88b6,
+	0x88cb,  0x88e0,  0x88f6,  0x890b,  0x8920,  0x8935,  0x894a,  0x8960,  0x8975,  0x898a,
+	0x899f,  0x89b4,  0x89ca,  0x89df,  0x89f4,  0x8a09,  0x8a1e,  0x8a34,  0x8a49,  0x8a5e,
+	0x8a73,  0x8a88,  0x8a9d,  0x8ab2,  0x8ac7,  0x8add,  0x8af2,  0x8b07,  0x8b1c,  0x8b31,
+	0x8b46,  0x8b5b,  0x8b70,  0x8b85,  0x8b9a,  0x8baf,  0x8bc5,  0x8bda,  0x8bef,  0x8c04,
+	0x8c19,  0x8c2e,  0x8c43,  0x8c58,  0x8c6d,  0x8c82,  0x8c97,  0x8cac,  0x8cc1,  0x8cd6,
+	0x8ceb,  0x8d00,  0x8d15,  0x8d2a,  0x8d3f,  0x8d54,  0x8d69,  0x8d7e,  0x8d93,  0x8da7,
+	0x8dbc,  0x8dd1,  0x8de6,  0x8dfb,  0x8e10,  0x8e25,  0x8e3a,  0x8e4f,  0x8e64,  0x8e79,
+	0x8e8d,  0x8ea2,  0x8eb7,  0x8ecc,  0x8ee1,  0x8ef6,  0x8f0b,  0x8f1f,  0x8f34,  0x8f49,
+	0x8f5e,  0x8f73,  0x8f88,  0x8f9c,  0x8fb1,  0x8fc6,  0x8fdb,  0x8ff0,  0x9004,  0x9019,
+	0x902e,  0x9043,  0x9057,  0x906c,  0x9081,  0x9096,  0x90aa,  0x90bf,  0x90d4,  0x90e9,
+	0x90fd,  0x9112,  0x9127,  0x913b,  0x9150,  0x9165,  0x9179,  0x918e,  0x91a3,  0x91b7,
+	0x91cc,  0x91e1,  0x91f5,  0x920a,  0x921f,  0x9233,  0x9248,  0x925d,  0x9271,  0x9286,
+	0x929a,  0x92af,  0x92c4,  0x92d8,  0x92ed,  0x9301,  0x9316,  0x932a,  0x933f,  0x9354,
+	0x9368,  0x937d,  0x9391,  0x93a6,  0x93ba,  0x93cf,  0x93e3,  0x93f8,  0x940c,  0x9421,
+	0x9435,  0x944a,  0x945e,  0x9473,  0x9487,  0x949c,  0x94b0,  0x94c5,  0x94d9,  0x94ee,
+	0x9502,  0x9516,  0x952b,  0x953f,  0x9554,  0x9568,  0x957d,  0x9591,  0x95a5,  0x95ba,
+	0x95ce,  0x95e2,  0x95f7,  0x960b,  0x9620,  0x9634,  0x9648,  0x965d,  0x9671,  0x9685,
+	0x969a,  0x96ae,  0x96c2,  0x96d7,  0x96eb,  0x96ff,  0x9713,  0x9728,  0x973c,  0x9750,
+	0x9765,  0x9779,  0x978d,  0x97a1,  0x97b6,  0x97ca,  0x97de,  0x97f2,  0x9807,  0x981b,
+	0x982f,  0x9843,  0x9857,  0x986c,  0x9880,  0x9894,  0x98a8,  0x98bc,  0x98d0,  0x98e5,
+	0x98f9,  0x990d,  0x9921,  0x9935,  0x9949,  0x995d,  0x9972,  0x9986,  0x999a,  0x99ae,
+	0x99c2,  0x99d6,  0x99ea,  0x99fe,  0x9a12,  0x9a26,  0x9a3a,  0x9a4f,  0x9a63,  0x9a77,
+	0x9a8b,  0x9a9f,  0x9ab3,  0x9ac7,  0x9adb,  0x9aef,  0x9b03,  0x9b17,  0x9b2b,  0x9b3f,
+	0x9b53,  0x9b67,  0x9b7b,  0x9b8f,  0x9ba3,  0x9bb7,  0x9bca,  0x9bde,  0x9bf2,  0x9c06,
+	0x9c1a,  0x9c2e,  0x9c42,  0x9c56,  0x9c6a,  0x9c7e,  0x9c92,  0x9ca6,  0x9cb9,  0x9ccd,
+	0x9ce1,  0x9cf5,  0x9d09,  0x9d1d,  0x9d31,  0x9d44,  0x9d58,  0x9d6c,  0x9d80,  0x9d94,
+	0x9da7,  0x9dbb,  0x9dcf,  0x9de3,  0x9df7,  0x9e0a,  0x9e1e,  0x9e32,  0x9e46,  0x9e59,
+	0x9e6d,  0x9e81,  0x9e95,  0x9ea8,  0x9ebc,  0x9ed0,  0x9ee3,  0x9ef7,  0x9f0b,  0x9f1f,
+	0x9f32,  0x9f46,  0x9f5a,  0x9f6d,  0x9f81,  0x9f95,  0x9fa8,  0x9fbc,  0x9fd0,  0x9fe3,
+	0x9ff7,  0xa00a,  0xa01e,  0xa032,  0xa045,  0xa059,  0xa06c,  0xa080,  0xa094,  0xa0a7,
+	0xa0bb,  0xa0ce,  0xa0e2,  0xa0f5,  0xa109,  0xa11c,  0xa130,  0xa143,  0xa157,  0xa16b,
+	0xa17e,  0xa192,  0xa1a5,  0xa1b9,  0xa1cc,  0xa1df,  0xa1f3,  0xa206,  0xa21a,  0xa22d,
+	0xa241,  0xa254,  0xa268,  0xa27b,  0xa28e,  0xa2a2,  0xa2b5,  0xa2c9,  0xa2dc,  0xa2ef,
+	0xa303,  0xa316,  0xa32a,  0xa33d,  0xa350,  0xa364,  0xa377,  0xa38a,  0xa39e,  0xa3b1,
+	0xa3c4,  0xa3d8,  0xa3eb,  0xa3fe,  0xa412,  0xa425,  0xa438,  0xa44b,  0xa45f,  0xa472,
+	0xa485,  0xa498,  0xa4ac,  0xa4bf,  0xa4d2,  0xa4e5,  0xa4f9,  0xa50c,  0xa51f,  0xa532,
+	0xa545,  0xa559,  0xa56c,  0xa57f,  0xa592,  0xa5a5,  0xa5b8,  0xa5cc,  0xa5df,  0xa5f2,
+	0xa605,  0xa618,  0xa62b,  0xa63e,  0xa652,  0xa665,  0xa678,  0xa68b,  0xa69e,  0xa6b1,
+	0xa6c4,  0xa6d7,  0xa6ea,  0xa6fd,  0xa710,  0xa723,  0xa736,  0xa749,  0xa75c,  0xa76f,
+	0xa782,  0xa795,  0xa7a8,  0xa7bb,  0xa7ce,  0xa7e1,  0xa7f4,  0xa807,  0xa81a,  0xa82d,
+	0xa840,  0xa853,  0xa866,  0xa879,  0xa88c,  0xa89f,  0xa8b2,  0xa8c5,  0xa8d7,  0xa8ea,
+	0xa8fd,  0xa910,  0xa923,  0xa936,  0xa949,  0xa95c,  0xa96e,  0xa981,  0xa994,  0xa9a7,
+	0xa9ba,  0xa9cd,  0xa9df,  0xa9f2,  0xaa05,  0xaa18,  0xaa2a,  0xaa3d,  0xaa50,  0xaa63,
+	0xaa76,  0xaa88,  0xaa9b,  0xaaae,  0xaac1,  0xaad3,  0xaae6,  0xaaf9,  0xab0b,  0xab1e,
+	0xab31,  0xab43,  0xab56,  0xab69,  0xab7b,  0xab8e,  0xaba1,  0xabb3,  0xabc6,  0xabd9,
+	0xabeb,  0xabfe,  0xac11,  0xac23,  0xac36,  0xac48,  0xac5b,  0xac6d,  0xac80,  0xac93,
+	0xaca5,  0xacb8,  0xacca,  0xacdd,  0xacef,  0xad02,  0xad14,  0xad27,  0xad39,  0xad4c,
+	0xad5e,  0xad71,  0xad83,  0xad96,  0xada8,  0xadbb,  0xadcd,  0xade0,  0xadf2,  0xae05,
+	0xae17,  0xae29,  0xae3c,  0xae4e,  0xae61,  0xae73,  0xae85,  0xae98,  0xaeaa,  0xaebd,
+	0xaecf,  0xaee1,  0xaef4,  0xaf06,  0xaf18,  0xaf2b,  0xaf3d,  0xaf4f,  0xaf62,  0xaf74,
+	0xaf86,  0xaf99,  0xafab,  0xafbd,  0xafcf,  0xafe2,  0xaff4,  0xb006,  0xb018,  0xb02b,
+	0xb03d,  0xb04f,  0xb061,  0xb074,  0xb086,  0xb098,  0xb0aa,  0xb0bc,  0xb0ce,  0xb0e1,
+	0xb0f3,  0xb105,  0xb117,  0xb129,  0xb13b,  0xb14e,  0xb160,  0xb172,  0xb184,  0xb196,
+	0xb1a8,  0xb1ba,  0xb1cc,  0xb1de,  0xb1f0,  0xb203,  0xb215,  0xb227,  0xb239,  0xb24b,
+	0xb25d,  0xb26f,  0xb281,  0xb293,  0xb2a5,  0xb2b7,  0xb2c9,  0xb2db,  0xb2ed,  0xb2ff,
+	0xb311,  0xb323,  0xb335,  0xb347,  0xb358,  0xb36a,  0xb37c,  0xb38e,  0xb3a0,  0xb3b2,
+	0xb3c4,  0xb3d6,  0xb3e8,  0xb3fa,  0xb40b,  0xb41d,  0xb42f,  0xb441,  0xb453,  0xb465,
+	0xb477,  0xb488,  0xb49a,  0xb4ac,  0xb4be,  0xb4d0,  0xb4e1,  0xb4f3,  0xb505,  0xb517,
+	0xb528,  0xb53a,  0xb54c,  0xb55e,  0xb56f,  0xb581,  0xb593,  0xb5a5,  0xb5b6,  0xb5c8,
+	0xb5da,  0xb5eb,  0xb5fd,  0xb60f,  0xb620,  0xb632,  0xb644,  0xb655,  0xb667,  0xb679,
+	0xb68a,  0xb69c,  0xb6ad,  0xb6bf,  0xb6d1,  0xb6e2,  0xb6f4,  0xb705,  0xb717,  0xb729,
+	0xb73a,  0xb74c,  0xb75d,  0xb76f,  0xb780,  0xb792,  0xb7a3,  0xb7b5,  0xb7c6,  0xb7d8,
+	0xb7e9,  0xb7fb,  0xb80c,  0xb81e,  0xb82f,  0xb841,  0xb852,  0xb864,  0xb875,  0xb886,
+	0xb898,  0xb8a9,  0xb8bb,  0xb8cc,  0xb8dd,  0xb8ef,  0xb900,  0xb912,  0xb923,  0xb934,
+	0xb946,  0xb957,  0xb968,  0xb97a,  0xb98b,  0xb99c,  0xb9ae,  0xb9bf,  0xb9d0,  0xb9e1,
+	0xb9f3,  0xba04,  0xba15,  0xba26,  0xba38,  0xba49,  0xba5a,  0xba6b,  0xba7d,  0xba8e,
+	0xba9f,  0xbab0,  0xbac1,  0xbad3,  0xbae4,  0xbaf5,  0xbb06,  0xbb17,  0xbb28,  0xbb3a,
+	0xbb4b,  0xbb5c,  0xbb6d,  0xbb7e,  0xbb8f,  0xbba0,  0xbbb1,  0xbbc3,  0xbbd4,  0xbbe5,
+	0xbbf6,  0xbc07,  0xbc18,  0xbc29,  0xbc3a,  0xbc4b,  0xbc5c,  0xbc6d,  0xbc7e,  0xbc8f,
+	0xbca0,  0xbcb1,  0xbcc2,  0xbcd3,  0xbce4,  0xbcf5,  0xbd06,  0xbd17,  0xbd28,  0xbd39,
+	0xbd4a,  0xbd5a,  0xbd6b,  0xbd7c,  0xbd8d,  0xbd9e,  0xbdaf,  0xbdc0,  0xbdd1,  0xbde2,
+	0xbdf2,  0xbe03,  0xbe14,  0xbe25,  0xbe36,  0xbe47,  0xbe57,  0xbe68,  0xbe79,  0xbe8a,
+	0xbe9b,  0xbeab,  0xbebc,  0xbecd,  0xbede,  0xbeee,  0xbeff,  0xbf10,  0xbf21,  0xbf31,
+	0xbf42,  0xbf53,  0xbf63,  0xbf74,  0xbf85,  0xbf95,  0xbfa6,  0xbfb7,  0xbfc7,  0xbfd8,
+	0xbfe9,  0xbff9,  0xc00a,  0xc01b,  0xc02b,  0xc03c,  0xc04c,  0xc05d,  0xc06e,  0xc07e,
+	0xc08f,  0xc09f,  0xc0b0,  0xc0c0,  0xc0d1,  0xc0e1,  0xc0f2,  0xc102,  0xc113,  0xc123,
+	0xc134,  0xc144,  0xc155,  0xc165,  0xc176,  0xc186,  0xc197,  0xc1a7,  0xc1b8,  0xc1c8,
+	0xc1d8,  0xc1e9,  0xc1f9,  0xc20a,  0xc21a,  0xc22a,  0xc23b,  0xc24b,  0xc25c,  0xc26c,
+	0xc27c,  0xc28d,  0xc29d,  0xc2ad,  0xc2be,  0xc2ce,  0xc2de,  0xc2ee,  0xc2ff,  0xc30f,
+	0xc31f,  0xc330,  0xc340,  0xc350,  0xc360,  0xc371,  0xc381,  0xc391,  0xc3a1,  0xc3b1,
+	0xc3c2,  0xc3d2,  0xc3e2,  0xc3f2,  0xc402,  0xc413,  0xc423,  0xc433,  0xc443,  0xc453,
+	0xc463,  0xc473,  0xc483,  0xc494,  0xc4a4,  0xc4b4,  0xc4c4,  0xc4d4,  0xc4e4,  0xc4f4,
+	0xc504,  0xc514,  0xc524,  0xc534,  0xc544,  0xc554,  0xc564,  0xc574,  0xc584,  0xc594,
+	0xc5a4,  0xc5b4,  0xc5c4,  0xc5d4,  0xc5e4,  0xc5f4,  0xc604,  0xc614,  0xc624,  0xc634,
+	0xc644,  0xc653,  0xc663,  0xc673,  0xc683,  0xc693,  0xc6a3,  0xc6b3,  0xc6c2,  0xc6d2,
+	0xc6e2,  0xc6f2,  0xc702,  0xc712,  0xc721,  0xc731,  0xc741,  0xc751,  0xc761,  0xc770,
+	0xc780,  0xc790,  0xc7a0,  0xc7af,  0xc7bf,  0xc7cf,  0xc7de,  0xc7ee,  0xc7fe,  0xc80d,
+	0xc81d,  0xc82d,  0xc83c,  0xc84c,  0xc85c,  0xc86b,  0xc87b,  0xc88b,  0xc89a,  0xc8aa,
+	0xc8ba,  0xc8c9,  0xc8d9,  0xc8e8,  0xc8f8,  0xc907,  0xc917,  0xc927,  0xc936,  0xc946,
+	0xc955,  0xc965,  0xc974,  0xc984,  0xc993,  0xc9a3,  0xc9b2,  0xc9c2,  0xc9d1,  0xc9e1,
+	0xc9f0,  0xc9ff,  0xca0f,  0xca1e,  0xca2e,  0xca3d,  0xca4d,  0xca5c,  0xca6b,  0xca7b,
+	0xca8a,  0xca99,  0xcaa9,  0xcab8,  0xcac7,  0xcad7,  0xcae6,  0xcaf5,  0xcb05,  0xcb14,
+	0xcb23,  0xcb33,  0xcb42,  0xcb51,  0xcb61,  0xcb70,  0xcb7f,  0xcb8e,  0xcb9e,  0xcbad,
+	0xcbbc,  0xcbcb,  0xcbda,  0xcbea,  0xcbf9,  0xcc08,  0xcc17,  0xcc26,  0xcc35,  0xcc45,
+	0xcc54,  0xcc63,  0xcc72,  0xcc81,  0xcc90,  0xcc9f,  0xccae,  0xccbe,  0xcccd,  0xccdc,
+	0xcceb,  0xccfa,  0xcd09,  0xcd18,  0xcd27,  0xcd36,  0xcd45,  0xcd54,  0xcd63,  0xcd72,
+	0xcd81,  0xcd90,  0xcd9f,  0xcdae,  0xcdbd,  0xcdcc,  0xcddb,  0xcdea,  0xcdf9,  0xce08,
+	0xce17,  0xce25,  0xce34,  0xce43,  0xce52,  0xce61,  0xce70,  0xce7f,  0xce8e,  0xce9c,
+	0xceab,  0xceba,  0xcec9,  0xced8,  0xcee7,  0xcef5,  0xcf04,  0xcf13,  0xcf22,  0xcf30,
+	0xcf3f,  0xcf4e,  0xcf5d,  0xcf6b,  0xcf7a,  0xcf89,  0xcf98,  0xcfa6,  0xcfb5,  0xcfc4,
+	0xcfd2,  0xcfe1,  0xcff0,  0xcffe,  0xd00d,  0xd01c,  0xd02a,  0xd039,  0xd047,  0xd056,
+	0xd065,  0xd073,  0xd082,  0xd090,  0xd09f,  0xd0ae,  0xd0bc,  0xd0cb,  0xd0d9,  0xd0e8,
+	0xd0f6,  0xd105,  0xd113,  0xd122,  0xd130,  0xd13f,  0xd14d,  0xd15c,  0xd16a,  0xd179,
+	0xd187,  0xd195,  0xd1a4,  0xd1b2,  0xd1c1,  0xd1cf,  0xd1de,  0xd1ec,  0xd1fa,  0xd209,
+	0xd217,  0xd225,  0xd234,  0xd242,  0xd250,  0xd25f,  0xd26d,  0xd27b,  0xd28a,  0xd298,
+	0xd2a6,  0xd2b5,  0xd2c3,  0xd2d1,  0xd2df,  0xd2ee,  0xd2fc,  0xd30a,  0xd318,  0xd326,
+	0xd335,  0xd343,  0xd351,  0xd35f,  0xd36d,  0xd37c,  0xd38a,  0xd398,  0xd3a6,  0xd3b4,
+	0xd3c2,  0xd3d0,  0xd3df,  0xd3ed,  0xd3fb,  0xd409,  0xd417,  0xd425,  0xd433,  0xd441,
+	0xd44f,  0xd45d,  0xd46b,  0xd479,  0xd487,  0xd495,  0xd4a3,  0xd4b1,  0xd4bf,  0xd4cd,
+	0xd4db,  0xd4e9,  0xd4f7,  0xd505,  0xd513,  0xd521,  0xd52f,  0xd53d,  0xd54b,  0xd559,
+	0xd566,  0xd574,  0xd582,  0xd590,  0xd59e,  0xd5ac,  0xd5ba,  0xd5c7,  0xd5d5,  0xd5e3,
+	0xd5f1,  0xd5ff,  0xd60c,  0xd61a,  0xd628,  0xd636,  0xd644,  0xd651,  0xd65f,  0xd66d,
+	0xd67a,  0xd688,  0xd696,  0xd6a4,  0xd6b1,  0xd6bf,  0xd6cd,  0xd6da,  0xd6e8,  0xd6f6,
+	0xd703,  0xd711,  0xd71f,  0xd72c,  0xd73a,  0xd747,  0xd755,  0xd763,  0xd770,  0xd77e,
+	0xd78b,  0xd799,  0xd7a6,  0xd7b4,  0xd7c1,  0xd7cf,  0xd7dc,  0xd7ea,  0xd7f8,  0xd805,
+	0xd812,  0xd820,  0xd82d,  0xd83b,  0xd848,  0xd856,  0xd863,  0xd871,  0xd87e,  0xd88b,
+	0xd899,  0xd8a6,  0xd8b4,  0xd8c1,  0xd8ce,  0xd8dc,  0xd8e9,  0xd8f6,  0xd904,  0xd911,
+	0xd91e,  0xd92c,  0xd939,  0xd946,  0xd954,  0xd961,  0xd96e,  0xd97b,  0xd989,  0xd996,
+	0xd9a3,  0xd9b0,  0xd9be,  0xd9cb,  0xd9d8,  0xd9e5,  0xd9f2,  0xda00,  0xda0d,  0xda1a,
+	0xda27,  0xda34,  0xda41,  0xda4f,  0xda5c,  0xda69,  0xda76,  0xda83,  0xda90,  0xda9d,
+	0xdaaa,  0xdab7,  0xdac4,  0xdad1,  0xdade,  0xdaeb,  0xdaf8,  0xdb05,  0xdb12,  0xdb1f,
+	0xdb2c,  0xdb39,  0xdb46,  0xdb53,  0xdb60,  0xdb6d,  0xdb7a,  0xdb87,  0xdb94,  0xdba1,
+	0xdbae,  0xdbbb,  0xdbc8,  0xdbd5,  0xdbe1,  0xdbee,  0xdbfb,  0xdc08,  0xdc15,  0xdc22,
+	0xdc2f,  0xdc3b,  0xdc48,  0xdc55,  0xdc62,  0xdc6f,  0xdc7b,  0xdc88,  0xdc95,  0xdca2,
+	0xdcae,  0xdcbb,  0xdcc8,  0xdcd5,  0xdce1,  0xdcee,  0xdcfb,  0xdd07,  0xdd14,  0xdd21,
+	0xdd2d,  0xdd3a,  0xdd47,  0xdd53,  0xdd60,  0xdd6c,  0xdd79,  0xdd86,  0xdd92,  0xdd9f,
+	0xddab,  0xddb8,  0xddc5,  0xddd1,  0xddde,  0xddea,  0xddf7,  0xde03,  0xde10,  0xde1c,
+	0xde29,  0xde35,  0xde42,  0xde4e,  0xde5b,  0xde67,  0xde74,  0xde80,  0xde8c,  0xde99,
+	0xdea5,  0xdeb2,  0xdebe,  0xdeca,  0xded7,  0xdee3,  0xdef0,  0xdefc,  0xdf08,  0xdf15,
+	0xdf21,  0xdf2d,  0xdf39,  0xdf46,  0xdf52,  0xdf5e,  0xdf6b,  0xdf77,  0xdf83,  0xdf8f,
+	0xdf9c,  0xdfa8,  0xdfb4,  0xdfc0,  0xdfcd,  0xdfd9,  0xdfe5,  0xdff1,  0xdffd,  0xe009,
+	0xe016,  0xe022,  0xe02e,  0xe03a,  0xe046,  0xe052,  0xe05e,  0xe06a,  0xe077,  0xe083,
+	0xe08f,  0xe09b,  0xe0a7,  0xe0b3,  0xe0bf,  0xe0cb,  0xe0d7,  0xe0e3,  0xe0ef,  0xe0fb,
+	0xe107,  0xe113,  0xe11f,  0xe12b,  0xe137,  0xe143,  0xe14f,  0xe15b,  0xe167,  0xe172,
+	0xe17e,  0xe18a,  0xe196,  0xe1a2,  0xe1ae,  0xe1ba,  0xe1c6,  0xe1d1,  0xe1dd,  0xe1e9,
+	0xe1f5,  0xe201,  0xe20d,  0xe218,  0xe224,  0xe230,  0xe23c,  0xe247,  0xe253,  0xe25f,
+	0xe26b,  0xe276,  0xe282,  0xe28e,  0xe299,  0xe2a5,  0xe2b1,  0xe2bd,  0xe2c8,  0xe2d4,
+	0xe2df,  0xe2eb,  0xe2f7,  0xe302,  0xe30e,  0xe31a,  0xe325,  0xe331,  0xe33c,  0xe348,
+	0xe353,  0xe35f,  0xe36b,  0xe376,  0xe382,  0xe38d,  0xe399,  0xe3a4,  0xe3b0,  0xe3bb,
+	0xe3c7,  0xe3d2,  0xe3de,  0xe3e9,  0xe3f4,  0xe400,  0xe40b,  0xe417,  0xe422,  0xe42e,
+	0xe439,  0xe444,  0xe450,  0xe45b,  0xe466,  0xe472,  0xe47d,  0xe488,  0xe494,  0xe49f,
+	0xe4aa,  0xe4b6,  0xe4c1,  0xe4cc,  0xe4d7,  0xe4e3,  0xe4ee,  0xe4f9,  0xe504,  0xe510,
+	0xe51b,  0xe526,  0xe531,  0xe53d,  0xe548,  0xe553,  0xe55e,  0xe569,  0xe574,  0xe57f,
+	0xe58b,  0xe596,  0xe5a1,  0xe5ac,  0xe5b7,  0xe5c2,  0xe5cd,  0xe5d8,  0xe5e3,  0xe5ee,
+	0xe5f9,  0xe605,  0xe610,  0xe61b,  0xe626,  0xe631,  0xe63c,  0xe647,  0xe652,  0xe65c,
+	0xe667,  0xe672,  0xe67d,  0xe688,  0xe693,  0xe69e,  0xe6a9,  0xe6b4,  0xe6bf,  0xe6ca,
+	0xe6d5,  0xe6df,  0xe6ea,  0xe6f5,  0xe700,  0xe70b,  0xe716,  0xe720,  0xe72b,  0xe736,
+	0xe741,  0xe74c,  0xe756,  0xe761,  0xe76c,  0xe777,  0xe781,  0xe78c,  0xe797,  0xe7a1,
+	0xe7ac,  0xe7b7,  0xe7c2,  0xe7cc,  0xe7d7,  0xe7e2,  0xe7ec,  0xe7f7,  0xe801,  0xe80c,
+	0xe817,  0xe821,  0xe82c,  0xe836,  0xe841,  0xe84c,  0xe856,  0xe861,  0xe86b,  0xe876,
+	0xe880,  0xe88b,  0xe895,  0xe8a0,  0xe8aa,  0xe8b5,  0xe8bf,  0xe8ca,  0xe8d4,  0xe8df,
+	0xe8e9,  0xe8f3,  0xe8fe,  0xe908,  0xe913,  0xe91d,  0xe927,  0xe932,  0xe93c,  0xe947,
+	0xe951,  0xe95b,  0xe966,  0xe970,  0xe97a,  0xe985,  0xe98f,  0xe999,  0xe9a3,  0xe9ae,
+	0xe9b8,  0xe9c2,  0xe9cc,  0xe9d7,  0xe9e1,  0xe9eb,  0xe9f5,  0xe9ff,  0xea0a,  0xea14,
+	0xea1e,  0xea28,  0xea32,  0xea3c,  0xea47,  0xea51,  0xea5b,  0xea65,  0xea6f,  0xea79,
+	0xea83,  0xea8d,  0xea97,  0xeaa1,  0xeaab,  0xeab6,  0xeac0,  0xeaca,  0xead4,  0xeade,
+	0xeae8,  0xeaf2,  0xeafc,  0xeb06,  0xeb0f,  0xeb19,  0xeb23,  0xeb2d,  0xeb37,  0xeb41,
+	0xeb4b,  0xeb55,  0xeb5f,  0xeb69,  0xeb73,  0xeb7c,  0xeb86,  0xeb90,  0xeb9a,  0xeba4,
+	0xebae,  0xebb7,  0xebc1,  0xebcb,  0xebd5,  0xebdf,  0xebe8,  0xebf2,  0xebfc,  0xec06,
+	0xec0f,  0xec19,  0xec23,  0xec2c,  0xec36,  0xec40,  0xec4a,  0xec53,  0xec5d,  0xec66,
+	0xec70,  0xec7a,  0xec83,  0xec8d,  0xec97,  0xeca0,  0xecaa,  0xecb3,  0xecbd,  0xecc6,
+	0xecd0,  0xecda,  0xece3,  0xeced,  0xecf6,  0xed00,  0xed09,  0xed13,  0xed1c,  0xed26,
+	0xed2f,  0xed38,  0xed42,  0xed4b,  0xed55,  0xed5e,  0xed68,  0xed71,  0xed7a,  0xed84,
+	0xed8d,  0xed97,  0xeda0,  0xeda9,  0xedb3,  0xedbc,  0xedc5,  0xedcf,  0xedd8,  0xede1,
+	0xedea,  0xedf4,  0xedfd,  0xee06,  0xee0f,  0xee19,  0xee22,  0xee2b,  0xee34,  0xee3e,
+	0xee47,  0xee50,  0xee59,  0xee62,  0xee6b,  0xee75,  0xee7e,  0xee87,  0xee90,  0xee99,
+	0xeea2,  0xeeab,  0xeeb4,  0xeebd,  0xeec7,  0xeed0,  0xeed9,  0xeee2,  0xeeeb,  0xeef4,
+	0xeefd,  0xef06,  0xef0f,  0xef18,  0xef21,  0xef2a,  0xef33,  0xef3c,  0xef45,  0xef4d,
+	0xef56,  0xef5f,  0xef68,  0xef71,  0xef7a,  0xef83,  0xef8c,  0xef95,  0xef9d,  0xefa6,
+	0xefaf,  0xefb8,  0xefc1,  0xefca,  0xefd2,  0xefdb,  0xefe4,  0xefed,  0xeff5,  0xeffe,
+	0xf007,  0xf010,  0xf018,  0xf021,  0xf02a,  0xf033,  0xf03b,  0xf044,  0xf04d,  0xf055,
+	0xf05e,  0xf067,  0xf06f,  0xf078,  0xf080,  0xf089,  0xf092,  0xf09a,  0xf0a3,  0xf0ab,
+	0xf0b4,  0xf0bc,  0xf0c5,  0xf0ce,  0xf0d6,  0xf0df,  0xf0e7,  0xf0f0,  0xf0f8,  0xf101,
+	0xf109,  0xf111,  0xf11a,  0xf122,  0xf12b,  0xf133,  0xf13c,  0xf144,  0xf14c,  0xf155,
+	0xf15d,  0xf166,  0xf16e,  0xf176,  0xf17f,  0xf187,  0xf18f,  0xf198,  0xf1a0,  0xf1a8,
+	0xf1b1,  0xf1b9,  0xf1c1,  0xf1c9,  0xf1d2,  0xf1da,  0xf1e2,  0xf1ea,  0xf1f3,  0xf1fb,
+	0xf203,  0xf20b,  0xf213,  0xf21b,  0xf224,  0xf22c,  0xf234,  0xf23c,  0xf244,  0xf24c,
+	0xf254,  0xf25d,  0xf265,  0xf26d,  0xf275,  0xf27d,  0xf285,  0xf28d,  0xf295,  0xf29d,
+	0xf2a5,  0xf2ad,  0xf2b5,  0xf2bd,  0xf2c5,  0xf2cd,  0xf2d5,  0xf2dd,  0xf2e5,  0xf2ed,
+	0xf2f5,  0xf2fd,  0xf304,  0xf30c,  0xf314,  0xf31c,  0xf324,  0xf32c,  0xf334,  0xf33c,
+	0xf343,  0xf34b,  0xf353,  0xf35b,  0xf363,  0xf36a,  0xf372,  0xf37a,  0xf382,  0xf38a,
+	0xf391,  0xf399,  0xf3a1,  0xf3a8,  0xf3b0,  0xf3b8,  0xf3c0,  0xf3c7,  0xf3cf,  0xf3d7,
+	0xf3de,  0xf3e6,  0xf3ed,  0xf3f5,  0xf3fd,  0xf404,  0xf40c,  0xf413,  0xf41b,  0xf423,
+	0xf42a,  0xf432,  0xf439,  0xf441,  0xf448,  0xf450,  0xf457,  0xf45f,  0xf466,  0xf46e,
+	0xf475,  0xf47d,  0xf484,  0xf48c,  0xf493,  0xf49a,  0xf4a2,  0xf4a9,  0xf4b1,  0xf4b8,
+	0xf4bf,  0xf4c7,  0xf4ce,  0xf4d5,  0xf4dd,  0xf4e4,  0xf4eb,  0xf4f3,  0xf4fa,  0xf501,
+	0xf509,  0xf510,  0xf517,  0xf51e,  0xf526,  0xf52d,  0xf534,  0xf53b,  0xf543,  0xf54a,
+	0xf551,  0xf558,  0xf55f,  0xf566,  0xf56e,  0xf575,  0xf57c,  0xf583,  0xf58a,  0xf591,
+	0xf598,  0xf59f,  0xf5a6,  0xf5ae,  0xf5b5,  0xf5bc,  0xf5c3,  0xf5ca,  0xf5d1,  0xf5d8,
+	0xf5df,  0xf5e6,  0xf5ed,  0xf5f4,  0xf5fb,  0xf602,  0xf609,  0xf610,  0xf616,  0xf61d,
+	0xf624,  0xf62b,  0xf632,  0xf639,  0xf640,  0xf647,  0xf64e,  0xf654,  0xf65b,  0xf662,
+	0xf669,  0xf670,  0xf677,  0xf67d,  0xf684,  0xf68b,  0xf692,  0xf698,  0xf69f,  0xf6a6,
+	0xf6ad,  0xf6b3,  0xf6ba,  0xf6c1,  0xf6c7,  0xf6ce,  0xf6d5,  0xf6db,  0xf6e2,  0xf6e9,
+	0xf6ef,  0xf6f6,  0xf6fd,  0xf703,  0xf70a,  0xf710,  0xf717,  0xf71e,  0xf724,  0xf72b,
+	0xf731,  0xf738,  0xf73e,  0xf745,  0xf74b,  0xf752,  0xf758,  0xf75f,  0xf765,  0xf76c,
+	0xf772,  0xf779,  0xf77f,  0xf785,  0xf78c,  0xf792,  0xf799,  0xf79f,  0xf7a5,  0xf7ac,
+	0xf7b2,  0xf7b8,  0xf7bf,  0xf7c5,  0xf7cb,  0xf7d2,  0xf7d8,  0xf7de,  0xf7e5,  0xf7eb,
+	0xf7f1,  0xf7f7,  0xf7fe,  0xf804,  0xf80a,  0xf810,  0xf816,  0xf81d,  0xf823,  0xf829,
+	0xf82f,  0xf835,  0xf83b,  0xf842,  0xf848,  0xf84e,  0xf854,  0xf85a,  0xf860,  0xf866,
+	0xf86c,  0xf872,  0xf878,  0xf87e,  0xf885,  0xf88b,  0xf891,  0xf897,  0xf89d,  0xf8a3,
+	0xf8a9,  0xf8af,  0xf8b4,  0xf8ba,  0xf8c0,  0xf8c6,  0xf8cc,  0xf8d2,  0xf8d8,  0xf8de,
+	0xf8e4,  0xf8ea,  0xf8f0,  0xf8f5,  0xf8fb,  0xf901,  0xf907,  0xf90d,  0xf913,  0xf918,
+	0xf91e,  0xf924,  0xf92a,  0xf930,  0xf935,  0xf93b,  0xf941,  0xf946,  0xf94c,  0xf952,
+	0xf958,  0xf95d,  0xf963,  0xf969,  0xf96e,  0xf974,  0xf97a,  0xf97f,  0xf985,  0xf98a,
+	0xf990,  0xf996,  0xf99b,  0xf9a1,  0xf9a6,  0xf9ac,  0xf9b2,  0xf9b7,  0xf9bd,  0xf9c2,
+	0xf9c8,  0xf9cd,  0xf9d3,  0xf9d8,  0xf9de,  0xf9e3,  0xf9e8,  0xf9ee,  0xf9f3,  0xf9f9,
+	0xf9fe,  0xfa04,  0xfa09,  0xfa0e,  0xfa14,  0xfa19,  0xfa1f,  0xfa24,  0xfa29,  0xfa2f,
+	0xfa34,  0xfa39,  0xfa3e,  0xfa44,  0xfa49,  0xfa4e,  0xfa54,  0xfa59,  0xfa5e,  0xfa63,
+	0xfa69,  0xfa6e,  0xfa73,  0xfa78,  0xfa7d,  0xfa83,  0xfa88,  0xfa8d,  0xfa92,  0xfa97,
+	0xfa9c,  0xfaa1,  0xfaa7,  0xfaac,  0xfab1,  0xfab6,  0xfabb,  0xfac0,  0xfac5,  0xfaca,
+	0xfacf,  0xfad4,  0xfad9,  0xfade,  0xfae3,  0xfae8,  0xfaed,  0xfaf2,  0xfaf7,  0xfafc,
+	0xfb01,  0xfb06,  0xfb0b,  0xfb10,  0xfb15,  0xfb1a,  0xfb1f,  0xfb23,  0xfb28,  0xfb2d,
+	0xfb32,  0xfb37,  0xfb3c,  0xfb40,  0xfb45,  0xfb4a,  0xfb4f,  0xfb54,  0xfb58,  0xfb5d,
+	0xfb62,  0xfb67,  0xfb6b,  0xfb70,  0xfb75,  0xfb7a,  0xfb7e,  0xfb83,  0xfb88,  0xfb8c,
+	0xfb91,  0xfb96,  0xfb9a,  0xfb9f,  0xfba4,  0xfba8,  0xfbad,  0xfbb1,  0xfbb6,  0xfbbb,
+	0xfbbf,  0xfbc4,  0xfbc8,  0xfbcd,  0xfbd1,  0xfbd6,  0xfbda,  0xfbdf,  0xfbe3,  0xfbe8,
+	0xfbec,  0xfbf1,  0xfbf5,  0xfbfa,  0xfbfe,  0xfc02,  0xfc07,  0xfc0b,  0xfc10,  0xfc14,
+	0xfc18,  0xfc1d,  0xfc21,  0xfc26,  0xfc2a,  0xfc2e,  0xfc33,  0xfc37,  0xfc3b,  0xfc3f,
+	0xfc44,  0xfc48,  0xfc4c,  0xfc51,  0xfc55,  0xfc59,  0xfc5d,  0xfc61,  0xfc66,  0xfc6a,
+	0xfc6e,  0xfc72,  0xfc76,  0xfc7b,  0xfc7f,  0xfc83,  0xfc87,  0xfc8b,  0xfc8f,  0xfc93,
+	0xfc97,  0xfc9b,  0xfca0,  0xfca4,  0xfca8,  0xfcac,  0xfcb0,  0xfcb4,  0xfcb8,  0xfcbc,
+	0xfcc0,  0xfcc4,  0xfcc8,  0xfccc,  0xfcd0,  0xfcd4,  0xfcd8,  0xfcdc,  0xfcdf,  0xfce3,
+	0xfce7,  0xfceb,  0xfcef,  0xfcf3,  0xfcf7,  0xfcfb,  0xfcfe,  0xfd02,  0xfd06,  0xfd0a,
+	0xfd0e,  0xfd12,  0xfd15,  0xfd19,  0xfd1d,  0xfd21,  0xfd24,  0xfd28,  0xfd2c,  0xfd30,
+	0xfd33,  0xfd37,  0xfd3b,  0xfd3e,  0xfd42,  0xfd46,  0xfd49,  0xfd4d,  0xfd51,  0xfd54,
+	0xfd58,  0xfd5b,  0xfd5f,  0xfd63,  0xfd66,  0xfd6a,  0xfd6d,  0xfd71,  0xfd74,  0xfd78,
+	0xfd7c,  0xfd7f,  0xfd83,  0xfd86,  0xfd89,  0xfd8d,  0xfd90,  0xfd94,  0xfd97,  0xfd9b,
+	0xfd9e,  0xfda2,  0xfda5,  0xfda8,  0xfdac,  0xfdaf,  0xfdb3,  0xfdb6,  0xfdb9,  0xfdbd,
+	0xfdc0,  0xfdc3,  0xfdc7,  0xfdca,  0xfdcd,  0xfdd0,  0xfdd4,  0xfdd7,  0xfdda,  0xfddd,
+	0xfde1,  0xfde4,  0xfde7,  0xfdea,  0xfdee,  0xfdf1,  0xfdf4,  0xfdf7,  0xfdfa,  0xfdfd,
+	0xfe01,  0xfe04,  0xfe07,  0xfe0a,  0xfe0d,  0xfe10,  0xfe13,  0xfe16,  0xfe19,  0xfe1c,
+	0xfe1f,  0xfe22,  0xfe25,  0xfe28,  0xfe2b,  0xfe2e,  0xfe31,  0xfe34,  0xfe37,  0xfe3a,
+	0xfe3d,  0xfe40,  0xfe43,  0xfe46,  0xfe49,  0xfe4c,  0xfe4f,  0xfe52,  0xfe55,  0xfe57,
+	0xfe5a,  0xfe5d,  0xfe60,  0xfe63,  0xfe66,  0xfe68,  0xfe6b,  0xfe6e,  0xfe71,  0xfe73,
+	0xfe76,  0xfe79,  0xfe7c,  0xfe7e,  0xfe81,  0xfe84,  0xfe87,  0xfe89,  0xfe8c,  0xfe8f,
+	0xfe91,  0xfe94,  0xfe97,  0xfe99,  0xfe9c,  0xfe9e,  0xfea1,  0xfea4,  0xfea6,  0xfea9,
+	0xfeab,  0xfeae,  0xfeb0,  0xfeb3,  0xfeb5,  0xfeb8,  0xfeba,  0xfebd,  0xfebf,  0xfec2,
+	0xfec4,  0xfec7,  0xfec9,  0xfecc,  0xfece,  0xfed1,  0xfed3,  0xfed5,  0xfed8,  0xfeda,
+	0xfedd,  0xfedf,  0xfee1,  0xfee4,  0xfee6,  0xfee8,  0xfeeb,  0xfeed,  0xfeef,  0xfef1,
+	0xfef4,  0xfef6,  0xfef8,  0xfefb,  0xfefd,  0xfeff,  0xff01,  0xff03,  0xff06,  0xff08,
+	0xff0a,  0xff0c,  0xff0e,  0xff10,  0xff13,  0xff15,  0xff17,  0xff19,  0xff1b,  0xff1d,
+	0xff1f,  0xff21,  0xff23,  0xff25,  0xff28,  0xff2a,  0xff2c,  0xff2e,  0xff30,  0xff32,
+	0xff34,  0xff36,  0xff38,  0xff3a,  0xff3b,  0xff3d,  0xff3f,  0xff41,  0xff43,  0xff45,
+	0xff47,  0xff49,  0xff4b,  0xff4d,  0xff4e,  0xff50,  0xff52,  0xff54,  0xff56,  0xff58,
+	0xff59,  0xff5b,  0xff5d,  0xff5f,  0xff60,  0xff62,  0xff64,  0xff66,  0xff67,  0xff69,
+	0xff6b,  0xff6c,  0xff6e,  0xff70,  0xff71,  0xff73,  0xff75,  0xff76,  0xff78,  0xff7a,
+	0xff7b,  0xff7d,  0xff7e,  0xff80,  0xff82,  0xff83,  0xff85,  0xff86,  0xff88,  0xff89,
+	0xff8b,  0xff8c,  0xff8e,  0xff8f,  0xff91,  0xff92,  0xff94,  0xff95,  0xff96,  0xff98,
+	0xff99,  0xff9b,  0xff9c,  0xff9d,  0xff9f,  0xffa0,  0xffa2,  0xffa3,  0xffa4,  0xffa6,
+	0xffa7,  0xffa8,  0xffa9,  0xffab,  0xffac,  0xffad,  0xffaf,  0xffb0,  0xffb1,  0xffb2,
+	0xffb4,  0xffb5,  0xffb6,  0xffb7,  0xffb8,  0xffb9,  0xffbb,  0xffbc,  0xffbd,  0xffbe,
+	0xffbf,  0xffc0,  0xffc1,  0xffc2,  0xffc4,  0xffc5,  0xffc6,  0xffc7,  0xffc8,  0xffc9,
+	0xffca,  0xffcb,  0xffcc,  0xffcd,  0xffce,  0xffcf,  0xffd0,  0xffd1,  0xffd2,  0xffd3,
+	0xffd4,  0xffd5,  0xffd5,  0xffd6,  0xffd7,  0xffd8,  0xffd9,  0xffda,  0xffdb,  0xffdc,
+	0xffdc,  0xffdd,  0xffde,  0xffdf,  0xffe0,  0xffe0,  0xffe1,  0xffe2,  0xffe3,  0xffe3,
+	0xffe4,  0xffe5,  0xffe6,  0xffe6,  0xffe7,  0xffe8,  0xffe8,  0xffe9,  0xffea,  0xffea,
+	0xffeb,  0xffec,  0xffec,  0xffed,  0xffed,  0xffee,  0xffef,  0xffef,  0xfff0,  0xfff0,
+	0xfff1,  0xfff1,  0xfff2,  0xfff2,  0xfff3,  0xfff3,  0xfff4,  0xfff4,  0xfff5,  0xfff5,
+	0xfff6,  0xfff6,  0xfff7,  0xfff7,  0xfff7,  0xfff8,  0xfff8,  0xfff9,  0xfff9,  0xfff9,
+	0xfffa,  0xfffa,  0xfffa,  0xfffb,  0xfffb,  0xfffb,  0xfffc,  0xfffc,  0xfffc,  0xfffc,
+	0xfffd,  0xfffd,  0xfffd,  0xfffd,  0xfffe,  0xfffe,  0xfffe,  0xfffe,  0xfffe,  0xffff,
+	0xffff,  0xffff,  0xffff,  0xffff,  0xffff,  0xffff,  0xffff,  0xffff,  0xffff,  0xffff,
+	0xffff,  0x0000,  0x0000,  0x0000,  0x0000,  0x0000};
+/* in actual sine / cosine functions, the last 5
+ * values will be added with a int '1' */
+
+/* FIXME: The coefficients could use a bit of cleanup */
+/*----------------------------------------------------------------------
+ * Function: ovl_util_sine()
+ * Description: Helper function for filter coefficient programming
+ *
+ * Notes in Usage:
+ *
+ *----------------------------------------------------------------------*/
+static int ovl_util_sine(int radiant_input)
+{
+
+	/*
+	 * the radiant input parameter is a 32 signed number where the LSB
+	 * 16 bits are the FP portion
+	 */
+
+	short sign = 0; /* 0 positive for and 1 for negative */
+	int pi_half_count = 0;
+	int pi_half = 0;
+	int balance = 0;
+	int answer = 0;
+
+	/* lets rule that the input is a signed integer in which:
+	 * the first 16 bits represent the integer
+	 * the last 16 bits represent the floating point portion */
+
+	/* first we have to normalize it to a positive number.*/
+	if(radiant_input<0)
+	{
+		sign = 1;
+		radiant_input = -radiant_input;
+	}
+
+	/* let's get pi/2 variable with 16 LSB FP just like this input data.*/
+	pi_half = 0x3243f; /* = 3.141586 */
+	pi_half += 0x1; /* for rounding off */
+	pi_half = pi_half >> 1; /* divided by 2 */
+
+
+	/* now we have to count how many pi/2 there are in this value
+	 * (since pi/2 = 90' = one quarter sine wave from 0 to 1) */
+	balance = radiant_input;
+	while(balance >= pi_half)
+	{
+		balance = balance - pi_half;
+		++pi_half_count;
+	}
+
+	/* using the pi_half_count, we can figure out how many 90 degrees.
+	 * thru the sine wave we are looking at */
+	pi_half_count = pi_half_count%4;
+
+	/*
+	 * balance is something between '0' and 'pi/2' - exactly what we need
+	 * to use in the table however, this is 16 bits shifted and our table
+	 * is a max of 12 bits - lets not forget to adjust but first we have to
+	 * use the balance according to which 90' of the sine wave we are in
+	 */
+
+	/* now we get the actual sine value of excess that's less than a
+	 * quarter pi if quart_count = 0, then answer is direct from table; */
+	if(pi_half_count == 0){
+
+		/* balance is now 16+13 = 29 fp portion BUT 20 bit numb */
+		balance = balance << 13;
+		/* balance is now 29 - 16 = 13 bit fp area BUT 14 bit numb */
+		balance = balance / pi_half;
+		balance = balance + 1; /* for round up */
+		balance = balance >> 1;
+		/* now balance should be a 13 bit number but */
+		/* bit 13 will never be '1' since balance was less than pi_half */
+
+		if(balance>4095) {
+			balance = 4095;
+		}
+		answer = wave_table[balance];
+		if(balance>4090) {
+			answer |= BIT16;
+		}
+	}
+
+	/* if quart_count = 1, then formula is =
+	 * answer = sin[(pi/2) - balance)] */
+	else if(pi_half_count == 1){
+		balance = pi_half - balance;
+
+		balance = balance << 13;
+		/* balance is now 16+13 = 29 fp portion BUT 20 bit numb */
+
+		balance = balance / pi_half;
+		/* balance is now 29 - 16 = 13 bit fp area BUT 14 bit numb */
+
+		balance = balance + 1; /* for round up */
+		balance = balance >> 1;
+		/* now balance should be a 13 bit number but */
+		/* bit 13 will never be '1' since balance was less than pi_half */
+
+		if(balance>4095) {
+			balance = 4095;
+		}
+
+		answer = wave_table[balance];
+		if(balance>4090) {
+			answer |= BIT16;
+		}
+	}
+
+	/*
+	 * if quart_count = 2, then formula is = answer = the negative of the
+	 * case it being 0;
+	 */
+	else if(pi_half_count == 2){
+
+		balance = balance << 13;
+		/* balance is now 16+13 = 29 fp portion BUT 20 bit numb */
+
+		balance = balance / pi_half;
+		/* balance is now 29 - 16 = 13 bit fp area BUT 14 bit numb */
+
+		balance = balance + 1; /* for round up */
+		balance = balance >> 1;
+		/* now balance should be a 13 bit number but */
+		/* bit 13 will never be '1' since balance was less than pi_half */
+
+		if(balance>4095) {
+			balance = 4095;
+		}
+
+		answer = wave_table[balance];
+		if(balance>4090) {
+			answer |= BIT16;
+		}
+		answer = 0 - answer;
+	}
+
+	/*
+	 * if quart_count = 3, then formula is = answer = the negative of the
+	 * case it being 1;
+	 */
+	else if(pi_half_count == 3){
+		balance = pi_half - balance;
+
+		balance = balance << 13;
+		/* balance is now 16+13 = 29 fp portion BUT 20 bit numb */
+
+		balance = balance / pi_half;
+		/* balance is now 29 - 16 = 13 bit fp area BUT 14 bit numb */
+
+		balance = balance + 1; /* for round up */
+		balance = balance >> 1;
+		/* now balance should be a 13 bit number but */
+		/* bit 13 will never be '1' since balance was less than pi_half */
+
+		if(balance>4095) {
+			balance = 4095;
+		}
+
+		answer = wave_table[balance];
+		if(balance>4090) {
+			answer |= BIT16;
+		}
+		answer = 0 - answer;
+	}
+
+	if(sign==1) {
+		answer = 0-answer;
+	}
+
+	return answer;
+	/*
+	 * so return value is a signed short where 16 MSBits are integer and
+	 * 16 LSBits are FP
+	 */
+}
+
+/*----------------------------------------------------------------------
+ * Function: ovl_util_cosine()
+ * Description: Helper function for filter coefficient programming
+ *
+ * Notes in Usage:
+ *
+ *----------------------------------------------------------------------*/
+static int ovl_util_cosine(int radiant_input)
+{
+	/*
+	 * the radiant input parameter is a 32 signed number where the LSB
+	 * 16 bits are the FP portion
+	 */
+
+	short sign = 0; /* 0 positive for and 1 for negative */
+	int pi_half_count = 0;
+	int pi_half = 0;
+	int balance = 0;
+	int answer = 0;
+
+	/* lets rule that the input is a signed integer in which:
+	 * the first 16 bits represent the integer
+	 * the last 16 bits represent the floating point portion */
+
+	/* first we have to normalize it to a positive number.*/
+	if(radiant_input<0) {
+		sign = 1;
+		radiant_input = -radiant_input;
+	}
+
+	/* let's get pi/2 variable with 16 LSB FP just like this input data.*/
+	pi_half = 0x3243f; /* = 3.141586 */
+	pi_half += 0x1; /* for rounding off */
+	pi_half = pi_half >> 1; /* divided by 2 */
+
+
+	/* now we have to count how many pi/2 there are in this value
+	 * (since pi/2 = 90' = one quarter sine wave from 0 to 1) */
+	balance = radiant_input;
+	while(balance >= pi_half) {
+		balance = balance - pi_half;
+		++pi_half_count;
+	}
+
+	/* using the pi_half_count, we can figure out how many 90 degrees.
+	 * thru the sine wave we are looking at */
+	pi_half_count = pi_half_count%4;
+
+	/*
+	 * balance is something between '0' and 'pi/2' - exactly what we need
+	 * to use in the table however, this is 16 bits shifted and our table
+	 * is a max of 12 bits - lets not forget to adjust but first we have
+	 * to use the balance according to which 90' of the sine wave we are in
+	 */
+
+	/* now we get the actual sine value of excess
+	 * that's less than a quarter pi
+	 * if quart_count = 0, then formula is = sine quarter # 1
+	 * then formula is = answer = sin[(pi/2) - balance)] */
+	if(pi_half_count == 0) {
+		balance = pi_half - balance;
+
+		balance = balance << 13;
+		/* balance is now 16+13 = 29 fp portion BUT 20 bit numb */
+
+		balance = balance / pi_half;
+		/* balance is now 29 - 16 = 13 bit fp area BUT 14 bit numb */
+
+		balance = balance + 1; /* for round up */
+		balance = balance >> 1;
+		/* now balance should be a 13 bit number but */
+		/* bit 13 will never be '1' since balance was less than pi_half */
+
+		if(balance>4095) {
+			balance = 4095;
+		}
+
+		answer = wave_table[balance];
+		if(balance>4090) {
+			answer |= BIT16;
+		}
+	}
+
+	/* if quart_count = 1, then formula is = sine quarter # 2
+	 * then formula is = answer = the negative of the case it being 0; */
+	else if(pi_half_count == 1){
+
+		balance = balance << 13;
+		/* balance is now 16+13 = 29 fp portion BUT 20 bit numb */
+
+		balance = balance / pi_half;
+		/* balance is now 29 - 16 = 13 bit fp area BUT 14 bit numb */
+
+		balance = balance + 1; /* for round up */
+		balance = balance >> 1;
+		/* now balance should be a 13 bit number but */
+		/* bit 13 will never be '1' since balance was less than pi_half */
+
+		if(balance>4095) {
+			balance = 4095;
+		}
+
+		answer = wave_table[balance];
+		if(balance>4090) {
+			answer |= BIT16;
+		}
+
+		answer = 0 - answer;
+	}
+
+	/*if quart_count = 2, then formula is = sine quarter # 3
+	 * then formula is = answer = the negative of the case it being 1; */
+	else if(pi_half_count == 2){
+		balance = pi_half - balance;
+
+		balance = balance << 13;
+		/* balance is now 16+13 = 29 fp portion BUT 20 bit numb */
+
+		balance = balance / pi_half;
+		/* balance is now 29 - 16 = 13 bit fp area BUT 14 bit numb */
+
+		balance = balance + 1; /* for round up */
+		balance = balance >> 1;
+		/* now balance should be a 13 bit number but */
+		/* bit 13 will never be '1' since balance was less than pi_half */
+
+		if(balance>4095) {
+			balance = 4095;
+		}
+
+		answer = wave_table[balance];
+		if(balance>4090) {
+			answer |= BIT16;
+		}
+		answer = 0 - answer;
+	}
+
+	/*if quart_count = 3, then formula is = sine quarter # 0
+	 * now we get the actual sine value of excess that's
+	 * less than a quarter pi then answer is direct from table;*/
+	else if(pi_half_count == 3){
+
+		balance = balance << 13;
+		/* balance is now 16+13 = 29 fp portion BUT 20 bit numb */
+
+		balance = balance / pi_half;
+		/* balance is now 29 - 16 = 13 bit fp area BUT 14 bit numb */
+
+		balance = balance + 1; /* for round up */
+		balance = balance >> 1;
+		/* now balance should be a 13 bit number but */
+		/* bit 13 will never be '1' since balance was less than pi_half */
+
+		if(balance>4095) {
+			balance = 4095;
+		}
+
+		answer = wave_table[balance];
+		if(balance>4090) {
+			answer |= BIT16;
+		}
+	}
+
+	if(sign==1) {
+		answer = 0-answer;
+	}
+
+	return answer;
+	/*
+	 * so return value is a signed short where bit_16 = integer and 16
+	 * LSBits are FP
+	 */
+}
+
+/*----------------------------------------------------------------------
+ * Function: ovl_set_coeff_reg()
+ * Description: Helper function for filter coefficient programming
+ *
+ * Notes in Usage:
+ *
+ *----------------------------------------------------------------------*/
+static unsigned int ovl_set_coeff_reg(
+	int * fpint_Coeff,
+	unsigned short wMantSize,
+	unsigned short * pCoeff,
+	unsigned short wPosition)
+{
+
+	/*
+	 * fpint_Coeff is a pointer to signed int that follows
+	 * MS 16 bits =integer, LS 16 bits =floating point for f.p. portion of
+	 * scaling
+	 */
+
+	unsigned short wRes;
+	unsigned short sign;
+	int coeff;
+	int maxVal;
+	int wCoeff_exp3;
+	int wCoeff_exp2;
+	int wCoeff_exp1;
+	int wCoeff_exp0;
+
+	sign = 0;
+	maxVal = 1 << wMantSize;
+	coeff = *fpint_Coeff;
+	if (coeff < 0) {
+		sign = 1;
+		coeff = - coeff;
+	}
+
+	wRes = 12 - wMantSize;
+
+	wCoeff_exp3 = coeff * 4;
+	wCoeff_exp2 = coeff * 2;
+	wCoeff_exp1 = coeff;
+	wCoeff_exp0 = coeff;
+	wCoeff_exp0 += BIT0;
+	wCoeff_exp0 = wCoeff_exp0 >> 1;
+
+	wCoeff_exp3 = wCoeff_exp3 + (1 << (16 - wMantSize -1));
+	/* round coeff to the nearest bit X */
+	/* where X is the last MS bit that will
+	 * be left out of the mantissa*/
+	wCoeff_exp3 = wCoeff_exp3 >> (16 - wMantSize);
+	/* now wCoeff is a unsigned short where */
+	/* FP portion matched maxVal */
+
+	wCoeff_exp2 = wCoeff_exp2 + (1 << (16 - wMantSize -1));
+	/* round coeff to the nearest bit X */
+	/* where X is the last MS bit that will
+	 * be left out of the mantissa */
+
+	wCoeff_exp2 = wCoeff_exp2 >> (16 - wMantSize);
+	/* now wCoeff is a unsigned short where */
+	/* FP portion matched maxVal */
+
+	wCoeff_exp1 = wCoeff_exp1 + (1 << (16 - wMantSize -1));
+	/* round coeff to the nearest bit X */
+	/* where X is the last MS bit that will
+	 * be left out of the mantissa */
+
+	wCoeff_exp1 = wCoeff_exp1 >> (16 - wMantSize);
+	/* now wCoeff is a unsigned short where */
+	/* FP portion matched maxVal */
+
+	wCoeff_exp0 = wCoeff_exp0 + (1 << (16 - wMantSize -1));
+	/* round coeff to the nearest bit X */
+	/* where X is the last MS bit that will
+	 * be left out of the mantissa */
+
+	wCoeff_exp0 = wCoeff_exp0 >> (16 - wMantSize);
+	/* now wCoeff is a unsigned short where */
+	/* FP portion matched maxVal */
+
+	pCoeff[wPosition] = 0;
+
+	if ( wCoeff_exp3 < maxVal ) {
+		pCoeff[wPosition] |= (3 << 12);/*exponent */
+		pCoeff[wPosition] |= (wCoeff_exp3 << wRes);/*mantissa*/
+
+		*fpint_Coeff = wCoeff_exp3 << (16 - wMantSize);
+		*fpint_Coeff += BIT1;
+		*fpint_Coeff = *fpint_Coeff >> 2;
+	} else if ( wCoeff_exp2 < maxVal ) {
+		pCoeff[wPosition] |= (2 << 12);/*.exponent */
+		pCoeff[wPosition] |= (wCoeff_exp2 << wRes);/*mantissa*/
+
+		*fpint_Coeff = wCoeff_exp2 << (16 - wMantSize);
+		*fpint_Coeff += BIT0;
+		*fpint_Coeff = *fpint_Coeff >> 1;
+	} else if ( wCoeff_exp1 < maxVal ) {
+		pCoeff[wPosition] |= (1 << 12);/*.exponent */
+		pCoeff[wPosition] |= (wCoeff_exp1 << wRes);/*mantissa*/
+
+		*fpint_Coeff = wCoeff_exp1 << (16 - wMantSize);
+	} else if ( wCoeff_exp0 < maxVal ) {
+		pCoeff[wPosition] |= (wCoeff_exp0 << wRes);/*mantissa*/
+
+		*fpint_Coeff = wCoeff_exp0 << (16 - wMantSize);
+		*fpint_Coeff = *fpint_Coeff * 2;
+	} else {
+		return 0; /*Coeff out of range*/
+	}
+
+	if(sign) {
+		pCoeff[wPosition] |= BIT15;/*sign */
+	}
+
+	if (sign) {
+		*fpint_Coeff = -(*fpint_Coeff);
+	}
+
+	return 1;
+
+}
+
+
+/*----------------------------------------------------------------------
+ * Function: ovl_update_coeff_regs()
+ * Description: Helper function for filter coefficient programming
+ *
+ * Notes in Usage:
+ *
+ *----------------------------------------------------------------------*/
+int ddCoeff[17][5];
+unsigned short wTapAdjust[5];
+void ovl_update_coeff_regs(
+	unsigned short wTaps,
+	int fpint_cutoff,
+	unsigned short bHor,
+	unsigned short bY,
+	unsigned short * pCoeff)
+{
+
+	unsigned short i, j, j1, num, pos, wMantSize;
+	unsigned short bVandC;
+
+	int val, sinc, window, sum, x, y;
+	int dCoeff[5*32];
+	int dDiff;
+	unsigned short wTap2Fix;
+
+	const int pi = 0x3243f; /* = 3.141586 << 16 */
+				  /*+- 3.1415926535; */
+
+	/* H Scale */
+	if (bHor==1)
+		wMantSize = 7;
+	else
+		wMantSize = 6;
+
+	/*vertal & Chroma */
+	if(bHor==0 && bY==0)
+		bVandC = 1;
+	else
+		bVandC = 0;
+
+	/*
+	 * 1 - let's make this fixed point number smaller by 4 bits,
+	 * since it will be a denominator later
+	 */
+	/* 2 - dont forget to round it at the 3rd bit */
+	fpint_cutoff += BIT3;
+	fpint_cutoff = fpint_cutoff >> 4; /* 16 bits of FP (reduced from 20) */
+
+	num = wTaps * 16;
+	for (i = 0; i < num*2; i++) {
+		/* fpint cutoff is 16 bits */
+		val = ((1 << 30)/fpint_cutoff);
+		/*14 bits of FP (after dividing the fpint_cutoff */
+		val += BIT3;
+		val = val >> 4; /* val is now 10 bits of FP */
+		val = val * wTaps * pi;
+		/*now 26 bits of FP (increase from 10 after multiply pi)*/
+		val += BIT5;
+		val = val >> 6; /*20 bits of FP (reduced from 26 bits)*/
+		val = val * (((i - num) << 8)/(2*num)); /*28 bits of FP now*/
+		if(val<0) {
+			val -= BIT11;
+		} else {
+			val += BIT11;
+		}
+		val = val >> 12; /* 16 bits of FP (reduced from 22 bits)*/
+
+		if (val == 0) {
+			sinc = (1 << 16); /*sinc = 1.0;*/
+		} else {
+			sinc = ovl_util_sine(val);
+			/* dont forget val has 14 bits of FP to it */
+			sinc = sinc << 12; /* sinc now has 28 bit FP */
+			if(val<0) {
+				val -= BIT3;
+			} else {
+				val += BIT3;
+			}
+			val = val >> 4; /* val now has 12 bit FP */
+			sinc = sinc / val; /* the new sinc is back to 16 bit FP */
+		}
+
+		/* hanning window */
+		window = (pi << 12)/num; /* 16 bits increased to 28 bits FP */
+		window += BIT11;
+		window = window >> 12;
+		window = i * window;
+		window = ovl_util_cosine(window);
+		/* note cosine param is 16 bits FP to it */
+		window += 1;
+		window = window >> 1; /* divided by 2 */
+		window = ((1 << 15) /*0.5*/ - window);
+
+		if(window<0) {
+			window -= BIT3;
+		} else {
+			window += BIT3;
+		}
+		window = window >> 4; /* now window is with 12 bit FP*/
+		if(sinc<0) {
+			sinc -= BIT3;
+		} else {
+			sinc += BIT3;
+		}
+		sinc = sinc >> 4; /* now sinc is with 12 bit FP */
+
+		dCoeff[i] = sinc * window;
+		/* dCoeff item is with 24 bit FP  --> lets reduce to 16*/
+		if(dCoeff[i]<0) {
+			dCoeff[i] -= BIT7;
+		} else {
+			dCoeff[i] += BIT7;
+		}
+		dCoeff[i] = dCoeff[i] >> 8;
+
+	}
+
+	for (i = 0; i < 17; i++) {
+		/* normalize the coefficient */
+		sum = 0;
+		for (j = 0; j < wTaps; j++) {
+			pos = i + j * 32;
+			sum += dCoeff[pos];
+			/* sum takes from dCeoff so it also has 16bit FP to it */
+		}
+		for (j = 0; j < wTaps; j++) {
+			pos = i + j * 32;
+			x = dCoeff[pos] << 11; /* x now has (16+11)=27 fp to it */
+			y = sum;
+			if(y<0)
+				y -= BIT7;
+			else
+				y += BIT7;
+			y = y >> 8; /* y now has (16-8)=8 fp to it */
+			ddCoeff[i][j] = x/y; /* ddCoeff has 27-8 = 19 fp to it */
+			if(ddCoeff[i][j] < 0)
+				ddCoeff[i][j] -= BIT2;
+			else
+				ddCoeff[i][j] += BIT2;
+			ddCoeff[i][j] = ddCoeff[i][j] >> 3;
+			/*ddCoeff is back to 16 bit fp (19-3) */
+		}
+
+		/*
+		 * set the coefficient registers and get the data in floating
+		 * point format
+		 */
+        for (j = 0; j < wTaps; j++) {
+			pos = j + i * wTaps;
+			if ( (j == (wTaps - 1)/2) && (!bVandC) ) {
+				ovl_set_coeff_reg(&ddCoeff[i][j],
+					(unsigned short)(wMantSize + 2),pCoeff,pos);
+			} else {
+				ovl_set_coeff_reg(&ddCoeff[i][j],
+					(unsigned short)wMantSize,pCoeff,pos);
+			}
+		}
+
+		wTapAdjust[0] = (wTaps - 1)/2;
+		for (j = 1, j1 = 1; j <= wTapAdjust[0]; j++, j1++) {
+			wTapAdjust[j1] = wTapAdjust[0] - j;
+			wTapAdjust[++j1] = wTapAdjust[0] + j;
+		}
+
+		/* adjust the coefficient */
+		sum = 0;
+		for (j = 0; j < wTaps; j++) {
+			sum += ddCoeff[i][j]; /*sum is now 16 bit fp to it*/
+		}
+
+		if (sum != (1 << 16)) {
+			/* if sum != 1.0 */
+			for (j1 = 0; j1 < wTaps; j1++) {
+				wTap2Fix = wTapAdjust[j1];
+				dDiff = (1 << 16) - sum; /*dDiff is also 16 bit FP to it*/
+				ddCoeff[i][wTap2Fix] += dDiff;
+				pos = wTap2Fix + i * wTaps;
+				if ( (wTap2Fix == (wTaps - 1)/2) && (!bVandC) ) {
+					ovl_set_coeff_reg(&ddCoeff[i][wTap2Fix],
+						(unsigned short)(wMantSize + 2),pCoeff,pos);
+				} else {
+					ovl_set_coeff_reg(&ddCoeff[i][wTap2Fix],
+						(unsigned short)wMantSize,pCoeff,pos);
+				}
+				sum = 0;
+				for (j = 0; j < wTaps; j++) {
+					sum += ddCoeff[i][j]; /*sum is now 16 bit FP to it*/
+				}
+				if (sum == (1 << 16 )) {
+					break;
+				}
+			}
+		}
+	}
+}
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_coeff.h b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_coeff.h
new file mode 100644
index 0000000..60cadb7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_coeff.h
@@ -0,0 +1,45 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_coeff.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the internal header file for overlay. It should be not be
+ *  by any other module besides the overlay module itself. It contains the
+ *  neccessary hardware virtualized structures and functions internal to
+ *  overlay
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OVL_COEFF_H
+#define _OVL_COEFF_H
+
+extern void ovl_update_coeff_regs(
+	unsigned short wTaps,
+	int fpint_cutoff,
+	unsigned short bHor,
+	unsigned short bY,
+	unsigned short * pCoeff);
+
+#endif  /* _OVL_COEFF_H */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_dispatch.h b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_dispatch.h
new file mode 100644
index 0000000..4487071
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_dispatch.h
@@ -0,0 +1,57 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_dispatch.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OVERLAY_DISPATCH_H
+#define _OVERLAY_DISPATCH_H
+
+typedef struct _ovl_dispatch {
+	int (*blend_surf_needed)(igd_display_context_t *display,
+		igd_surface_t       *src_surf,
+		igd_rect_t          *src_rect,
+		igd_rect_t          *dest_rect,
+		unsigned int         flags,
+		igd_surface_t       *blend_surf,
+		igd_rect_t          *blend_rect);
+	int (*alter_ovl)(igd_display_context_t *display,
+		igd_surface_t       *src_surf,
+		igd_rect_t          *src_rect,
+		igd_rect_t          *dest_rect,
+		igd_ovl_info_t      *ovl_info,
+		unsigned int         flags);
+	int (*query_ovl)(igd_display_h display_h,
+		unsigned int flags);
+	int (*query_max_size_ovl)(igd_display_h display_h,
+		unsigned long pf,
+		unsigned int *max_width,
+		unsigned int *max_height);
+} ovl_dispatch_t;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_virt.h b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_virt.h
new file mode 100644
index 0000000..7b0a998
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/cmn/ovl_virt.h
@@ -0,0 +1,107 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_virt.h
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the internal header file for overlay. It should be not be
+ *  by any other module besides the overlay module itself. It contains the
+ *  neccessary hardware virtualized structures and functions internal to
+ *  overlay
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OVL_VIRT_H
+#define _OVL_VIRT_H
+
+/* None of the IALs use the OVL_SUPPORT_*.  Exclude it for now. */
+/* None of the IALs use the OVL_RULE_MUST_*.  Exclude it for now. */
+
+/* Overlay HW range of values for color control and gamma correction*/
+#define OVL_HW_DEF_BRIGHT      750L
+#define OVL_HW_MIN_BRIGHT      0L
+#define OVL_HW_MAX_BRIGHT      10000L
+
+#define OVL_HW_DEF_CONT	    10000L
+#define OVL_HW_MIN_CONT	    0L
+#define OVL_HW_MAX_CONT	    20000L
+
+#define OVL_HW_DEF_SAT	        10000L
+#define OVL_HW_MIN_SAT		    0L
+#define OVL_HW_MAX_SAT	        20000L
+
+#define OVL_HW_DEF_HUE			0L
+#define OVL_HW_MIN_HUE			-180L
+#define OVL_MHW_AX_HUE			180L
+
+#define OVL_HW_DEF_GAMMA       1L
+#define OVL_HW_MAX_GAMMA       500L
+#define OVL_HW_MIN_GAMMA       1L
+
+#define OVL_REPROG_OP_NONE            0
+#define OVL_REPROG_OP_TURNON_PRIM     1
+#define OVL_REPROG_OP_TURNON_SECND    2
+#define OVL_REPROG_OP_TURNOFF_PRIM    3
+#define OVL_REPROG_OP_TURNOFF_SECND   4
+#define OVL_REPROG_OP_SWITCH_TO_PRIM  5
+#define OVL_REPROG_OP_SWITCH_TO_SECND 6
+#define OVL_REPROG_OP_REVERT_SECND	  7
+#define OVL_REPROG_OP_REVERT_PRIM	  8
+
+enum {
+	OVL_STATE_OFF = 0,
+	OVL_STATE_ON,
+};
+
+#define OVL_PRIMARY   0
+#define OVL_SECONDARY 1
+#define OVL_MAX_HW    2  /* Maximum number of overlays */
+
+/* Define the maximum number of blend surfaces which can be used */
+#define MAX_BLEND_SURF 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/drivers/gpu/drm/emgd/emgd/video/overlay/plb/micro_ovl_plb.c b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/micro_ovl_plb.c
new file mode 100644
index 0000000..c58e890
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/micro_ovl_plb.c
@@ -0,0 +1,1725 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: micro_ovl_plb.c
+ * $Revision: 1.17 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains function that actually programs the second
+ *  overlay with the bits to properly configure the overlay
+ *  Also includes functions to execute the second overlay flip
+ *  instruction, and query the overlay flip status.
+ *  Also contains some hardware capabilities querrying functions
+ *  for upper overlay layer to get this chips second overlay
+ *  capabilities
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.overlay
+
+#include <math_fix.h>
+#include <plb/cmd.h>
+#include "ovl_plb_cache.h"
+#include "ovl2_plb.h"
+#include "../cmn/ovl_dispatch.h"
+#include "../cmn/ovl_virt.h"
+
+extern unsigned long sprite_pixel_formats_plb[];
+
+extern unsigned int ovl2_check_plb(igd_display_context_t *display,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	igd_ovl_info_t      *ovl_info,
+	unsigned int         flags);
+
+int micro_alter_ovl2_plb(igd_display_context_t *display,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	igd_ovl_info_t      *ovl_info,
+	unsigned int         flags);
+
+#ifndef CONFIG_MICRO_OVERLAY
+#define	OVL2_CHECK_PLB_RET(ret,a, b, c, d, e,f) ret = ovl2_check_plb(a ,b ,c ,d ,e ,f)
+#define QUERY_OVL2_PLB_RET(ret,a, b) ret = query_ovl2_plb(a, b)
+#else
+#define	OVL2_CHECK_PLB_RET(ret,a, b, c, d, e,f) 0
+#define QUERY_OVL2_PLB_RET(ret,a, b) 0
+#endif
+
+ovl_dispatch_t ovl_micro_dispatch_plb[] = {
+	{
+		NULL,
+		micro_alter_ovl2_plb,
+		NULL,
+		NULL,
+	},
+};
+
+#ifndef OVL_PLB_CACHE_QUICK_SWAP /* If caching is NOT enabled */
+unsigned int micro_spritec_update_src_plb(igd_display_context_t *display,
+	ovl2_reg_plb_t *spritec_regs_plb,
+	igd_surface_t *src_surf,
+	igd_rect_t    *src_rect)
+{
+	unsigned int      src_Bpp;
+
+	EMGD_TRACE_ENTER;
+
+	/* This is in Bytes per pixel */
+	src_Bpp = IGD_PF_BPP(src_surf->pixel_format)/8;
+
+	/* src surface */
+	spritec_regs_plb->start = src_surf->offset +
+		(src_rect->y1 * src_surf->pitch) + (src_rect->x1 * src_Bpp);
+
+	EMGD_WRITE32(src_surf->pitch,
+		MMIO(display) + 0x72188);
+
+	/* src pixel format */
+	switch(src_surf->pixel_format){
+	case IGD_PF_YUV422_PACKED_YUY2:
+		spritec_regs_plb->control |= OVL2_CMD_YUV_422;
+		break;
+	case IGD_PF_YUV422_PACKED_UYVY:
+		spritec_regs_plb->control |= OVL2_CMD_YUV_422 | OVL2_CMD_UYVY;
+		break;
+	case IGD_PF_ARGB32_8888:
+		spritec_regs_plb->control |= OVL2_CMD_ARGB_8888;
+		break;
+	case IGD_PF_xRGB32_8888:
+		spritec_regs_plb->control |= OVL2_CMD_RGB_8888;
+		break;
+	case IGD_PF_RGB16_565:
+		spritec_regs_plb->control |= OVL2_CMD_RGB_565;
+		break;
+	case IGD_PF_xRGB16_555:
+	case IGD_PF_ARGB16_1555:
+		spritec_regs_plb->control |= OVL2_CMD_RGB_555;
+		break;
+	case IGD_PF_ARGB8_INDEXED:
+		spritec_regs_plb->control |= OVL2_CMD_RGB_8;
+		break;
+	default:
+		EMGD_ERROR_EXIT("Invalid pixel format: 0x%lx", src_surf->pixel_format);
+		return -IGD_ERROR_HWERROR;
+	}
+
+	/* Turn off YUV to RGB conversion if the src is RGB */
+	if (!(src_surf->pixel_format & PF_TYPE_YUV)) {
+		spritec_regs_plb->control |= (1<<19);
+	}
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+ * Function: spritec_update_video_quality_plb()
+ *
+ * Description:
+ *   This function updates the contrast, brightness, and saturation of
+ *   the overlay using the values specified in overlay_info.
+ *
+ * Returns:
+ *   != 0 on Error
+ *   0 on Success
+ *----------------------------------------------------------------------*/
+
+static int micro_spritec_update_video_quality_plb(
+	igd_display_context_t        *display,
+	igd_surface_t                *src_surf,
+	igd_ovl_video_quality_info_t *video_quality)
+{
+	int                          calc_brightness_tmp = 0;
+	int                          calc_brightness     = 0;
+	unsigned int                 calc_contrast_tmp   = 0;
+	unsigned int                 calc_contrast       = 0;
+	unsigned int                 calc_saturation_tmp = 0;
+	unsigned int                 calc_saturation     = 0;
+
+	EMGD_TRACE_ENTER;
+
+	/* If the src_surf pixel format is RGB, then brightness, contrast,
+	 * and saturation should all be set to the exact default */
+	if (src_surf->pixel_format & PF_TYPE_RGB) {
+		if (video_quality->brightness != 0x8000) {
+			EMGD_DEBUG("RGB surfaces must set brightness to default");
+		}
+		if (video_quality->contrast != 0x8000) {
+			EMGD_DEBUG("RGB surfaces must set contrast to default");
+		}
+		if (video_quality->saturation != 0x8000) {
+			EMGD_DEBUG("RGB surfaces must set saturation to default");
+		}
+
+		EMGD_WRITE32(OVL2_RGB_COLOR_DEF_CONT_BRGHT,
+			MMIO(display) + 0x721D0);
+		EMGD_WRITE32(OVL2_RGB_COLOR_DEF_SATN_HUE,
+			MMIO(display) + 0x721D4);
+
+		EMGD_TRACE_EXIT;
+		return IGD_SUCCESS;
+	}
+
+	/*************************************************************************
+	 * Brightness
+	 *************************************************************************/
+	if (0x8000 == video_quality->brightness) {
+		calc_brightness = MID_BRIGHTNESS_YUV;
+	} else if (video_quality->brightness < 0x8000) {
+		/*
+		 * we have here a brightness that is less than the default
+		 * mid point
+		 */
+		calc_brightness_tmp = 0x8000 - video_quality->brightness;
+		calc_brightness_tmp <<= 14;
+		calc_brightness_tmp /= 0x8000;
+		calc_brightness     = -128 - MID_BRIGHTNESS_YUV;
+		/*
+		 * more range if the midpoint is positive but less range
+		 * if midpoint is negative
+		 */
+
+		calc_brightness *= calc_brightness_tmp;
+		calc_brightness += BIT13;
+		calc_brightness >>= 14;
+
+		if (calc_brightness < -128) {
+			calc_brightness = -128;
+		}
+		if (calc_brightness > MID_BRIGHTNESS_YUV) {
+			calc_brightness = MID_BRIGHTNESS_YUV;
+		}
+	} else {
+		/*
+		 * we have here a brightness that is more than the default
+		 * mid point
+		 */
+		calc_brightness_tmp = video_quality->brightness - 0x8000;
+		calc_brightness_tmp <<= 14;
+		calc_brightness_tmp /= 0x8000;
+		calc_brightness     = 127 - MID_BRIGHTNESS_YUV;
+		/*
+		 * less range if the midpoint is positive but more range
+		 * if midpoint is negative
+		 */
+		calc_brightness *= calc_brightness_tmp;
+		calc_brightness += BIT13;
+		calc_brightness >>= 14;
+
+		if (calc_brightness > 127) {
+			calc_brightness = 127;
+		}
+		if (calc_brightness < MID_BRIGHTNESS_YUV) {
+			calc_brightness = MID_BRIGHTNESS_YUV;
+		}
+	}
+
+	EMGD_WRITE32((EMGD_READ32(MMIO(display) + 0x721D0) & 0xFFFFFF00) |
+		(calc_brightness & 0xFF),
+		MMIO(display) + 0x721D0);
+
+
+	/*************************************************************************
+	 * Contrast
+	 *************************************************************************/
+	if (0x8000 == video_quality->contrast ){
+		calc_contrast = MID_CONTRAST_YUV;
+	} else if (video_quality->contrast < 0x8000) {
+		/* we have here a contrast that is less than the
+		 * default mid point */
+		calc_contrast_tmp = video_quality->contrast;
+		calc_contrast_tmp <<= 12;
+		calc_contrast_tmp /= 0x8000;
+		calc_contrast     = MID_CONTRAST_YUV;
+		calc_contrast     *= calc_contrast_tmp;
+		calc_contrast     += BIT11;
+		calc_contrast     >>= 12;
+		if (calc_contrast > 0x3F) {
+			calc_contrast = 0x3F;
+		}
+	} else {
+		/* we have here a contrast that is more than the
+		 * default mid point */
+		calc_contrast_tmp = video_quality->contrast - 0x8000;
+		calc_contrast_tmp <<= 12;
+		calc_contrast_tmp /= 0x8000;
+		calc_contrast     = (0x1FF - MID_CONTRAST_YUV);
+		calc_contrast     *= calc_contrast_tmp;
+		calc_contrast     += BIT11;
+		calc_contrast     >>= 12;
+		calc_contrast     += MID_CONTRAST_YUV;
+		if (calc_contrast > 0x1FF) {
+			calc_contrast = 0x1FF;
+		}
+	}
+
+	EMGD_WRITE32((EMGD_READ32(MMIO(display) + 0x721D0) & 0xF803FFFF) |
+		((calc_contrast & 0x1FF) << 18),
+		MMIO(display) + 0x721D0);
+
+	/*************************************************************************
+	 * Saturation
+	 *************************************************************************/
+	if (video_quality->saturation == 0x8000) {
+		calc_saturation = MID_SATURATION_YUV;
+	} else if (video_quality->saturation < 0x8000) {
+		/* we have here a saturation that is less than the default
+		 * mid point */
+		calc_saturation_tmp = video_quality->saturation;
+		calc_saturation_tmp <<= 12;
+		calc_saturation_tmp /= 0x8000;
+		calc_saturation     = MID_SATURATION_YUV;
+		calc_saturation     *= calc_saturation_tmp;
+		calc_saturation     += BIT11;
+		calc_saturation     >>= 12;
+		if (calc_saturation > 0x7F) {
+			calc_saturation = 0x7F;
+		}
+	} else {
+		/* we have here a saturation that is more than the default
+		 * mid point*/
+		calc_saturation_tmp = video_quality->saturation - 0x8000;
+		calc_saturation_tmp <<= 12;
+		calc_saturation_tmp /= 0x8000;
+		calc_saturation     = (0x3FF - MID_SATURATION_YUV);
+		calc_saturation     *= calc_saturation_tmp;
+		calc_saturation     += BIT11;
+		calc_saturation     >>= 12;
+		calc_saturation     += MID_SATURATION_YUV;
+
+		if (calc_saturation > 0x3FF) {
+			calc_saturation = 0x3FF;
+		}
+	}
+
+	EMGD_WRITE32((EMGD_READ32(MMIO(display) + 0x721D4) & 0xFFFFFC00) |
+		(calc_saturation & 0x3FF),
+		MMIO(display) + 0x721D4);
+
+
+	/*************************************************************************
+	 * Hue
+	 *************************************************************************/
+	/* Hue is always set to the default value.  It is based on the saturation
+	 * value, and having a separate hue is of minimal value. */
+	EMGD_WRITE32(EMGD_READ32(MMIO(display) + 0x721D4) & 0xF800FFFF,
+		MMIO(display) + 0x721D4);
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: spritec_update_gamma_plb()
+ *
+ * Description:
+ *    This function sets the gamma correction values for the overlays.
+ *
+ * Returns:
+ *   != 0 on Error
+ *   IGD_SUCCESS on Success
+ *---------------------------------------------------------------------------*/
+static int micro_spritec_update_gamma_plb(
+	igd_display_context_t *display,
+	ovl2_reg_plb_t *spritec_regs_plb,
+	igd_ovl_gamma_info_t * ovl_gamma)
+{
+	const int gamma_reg_input[OVL2_TOTAL_GAMMA_REG] = {8, 16, 32, 64, 128, 192};
+	const int gamma_reg_offset[OVL2_TOTAL_GAMMA_REG] = {
+		OVL2_REG_ADDR_GAMMA0,
+		OVL2_REG_ADDR_GAMMA1,
+		OVL2_REG_ADDR_GAMMA2,
+		OVL2_REG_ADDR_GAMMA3,
+		OVL2_REG_ADDR_GAMMA4,
+		OVL2_REG_ADDR_GAMMA5
+	};
+	const unsigned int gamma_def[OVL2_TOTAL_GAMMA_REG] = {
+		0x00080808,
+		0x00101010,
+		0x00202020,
+		0x00404040,
+		0x00808080,
+		0x00c0c0c0
+	};
+	unsigned int          new_gamma_red_24i_8f, new_gamma_green_24i_8f;
+	unsigned int          new_gamma_blue_24i_8f;
+	unsigned int          gamma_normal_r_24i_8f;
+	unsigned int          gamma_normal_g_24i_8f;
+	unsigned int          gamma_normal_b_24i_8f;
+	unsigned int          gamma_reg, gamma_reg_24i_8f;
+	unsigned int          i;
+
+	EMGD_TRACE_ENTER;
+
+	/* FIXME: The gamma values are re-written for every alter_ovl call.
+	 * This may cause issues or may be to slow?  If so, store the previous
+	 * values and only re-write when they change. */
+
+	/* If the overlay gamma is disabled or the display is an 8 bit mode
+	 * (second overay can not support gamma in an 8 bit mode),
+	 * set it to the default */
+	if (((ovl_gamma->flags & IGD_OVL_GAMMA_ENABLE) == IGD_OVL_GAMMA_DISABLE) ||
+		(PLANE(display)->fb_info->pixel_format == IGD_PF_ARGB8_INDEXED)) {
+		for (i = 0; i < OVL2_TOTAL_GAMMA_REG; i++) {
+			/* program register */
+			EMGD_WRITE32(gamma_def[i], MMIO(display) + gamma_reg_offset[i]);
+		}
+		EMGD_TRACE_EXIT;
+		return IGD_SUCCESS;
+	}
+
+	/* It is assumed that the input value is a 24-bit number */
+	new_gamma_red_24i_8f   = ovl_gamma->red;
+	new_gamma_green_24i_8f = ovl_gamma->green;
+	new_gamma_blue_24i_8f  = ovl_gamma->blue;
+
+	/*
+	 * Program RGB for each of the 6 gamma registers
+	 */
+
+	/* Since the OS_POW_FIX function can only take an integer base,
+	 * we need to normalize the result by gamma_normal_x
+	 */
+	gamma_normal_r_24i_8f =  OS_POW_FIX(255, (1<<16)/new_gamma_red_24i_8f);
+	gamma_normal_g_24i_8f =  OS_POW_FIX(255, (1<<16)/new_gamma_green_24i_8f);
+	gamma_normal_b_24i_8f =  OS_POW_FIX(255, (1<<16)/new_gamma_blue_24i_8f);
+
+	for( i = 0; i < OVL2_TOTAL_GAMMA_REG; i++ )
+	{
+		/* red */
+		gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+								(1<<16)/new_gamma_red_24i_8f);
+		gamma_reg        =
+			((255 * gamma_reg_24i_8f) / gamma_normal_r_24i_8f) << 16;
+
+		/* green */
+		gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+							(1<<16)/new_gamma_green_24i_8f);
+		gamma_reg        |=
+			((255 * gamma_reg_24i_8f) / gamma_normal_g_24i_8f) << 8;
+
+		/* blue */
+		gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+							(1<<16)/new_gamma_blue_24i_8f);
+		gamma_reg        |=
+			((255 * gamma_reg_24i_8f) / gamma_normal_b_24i_8f);
+
+		/* turn overlay off (TBD) */
+
+		/* program register */
+		EMGD_WRITE32(gamma_reg, MMIO(display) + gamma_reg_offset[i]);
+
+		/* turn overlay on (TBD) */
+	}
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+#endif // End if caching is not enabled.
+
+static unsigned int convert_color_key_to_hw (
+	unsigned long pf,
+	unsigned int input)
+{
+	unsigned int output;
+
+	switch (pf) {
+	case IGD_PF_ARGB32:
+	case IGD_PF_xRGB32:
+	case IGD_PF_ARGB8_INDEXED:
+	default:
+		output = input;
+		break;
+	case IGD_PF_RGB16_565:
+		output =
+			((((input & 0xf800)>>11)<<3)<<16) |
+			((((input & 0x07e0)>>5 )<<2)<<8 ) |
+			((((input & 0x001f)>>0 )<<3)<<0 );
+		break;
+	case IGD_PF_ARGB16_1555:
+		output =
+			((((input & 0x7c00)>>10)<<3)<<16) |
+			((((input & 0x03e0)>>5 )<<3)<<8 ) |
+			((((input & 0x001f)>>0 )<<3)<<0 );
+		break;
+	}
+
+	return output;
+}
+static unsigned int convert_color_key_to_mask (
+	unsigned long pf,
+	unsigned int input)
+{
+	unsigned int output;
+
+	switch (pf) {
+	case IGD_PF_ARGB32:
+	case IGD_PF_xRGB32:
+	default:
+		output = 0x00ffffff;
+		break;
+	case IGD_PF_RGB16_565:
+		output = 0x00f8fcf8;
+		break;
+	case IGD_PF_ARGB16_1555:
+		output = 0x00f8f8f8;
+		break;
+	case IGD_PF_ARGB8_INDEXED:
+		output = 0x000000ff;
+		break;
+	}
+
+	return output;
+}
+
+/* Convert YUV to UVY for YUV pixel formats.
+ * Do not convert RGB pixel formats */
+static unsigned int yuv_to_uvy(
+	unsigned long pf,
+	unsigned int input)
+{
+	unsigned int output;
+
+	if (IGD_PF_TYPE(pf) & PF_TYPE_YUV) {
+		output =
+			((input & 0x00ff0000) >> 16) |
+			((input & 0x0000ff00) << 8)  |
+			((input & 0x000000ff) << 8);
+	} else {
+		output = input;
+	}
+
+	return output;
+}
+
+#ifndef OVL_PLB_CACHE_QUICK_SWAP /* If caching is NOT enabled */
+
+static unsigned int micro_spritec_update_regs_plb(
+	igd_display_context_t *display,
+	ovl2_reg_plb_t      *spritec_regs_plb,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	igd_ovl_info_t      *ovl_info,
+	unsigned int         flags)
+{
+	unsigned int plane_control, plane_start;
+	unsigned int pipe_num;
+	unsigned int ckey_low, ckey_high;
+	int ret;
+
+
+	EMGD_TRACE_ENTER;
+
+	if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+		/* Turn off the plane control key enable and the second overlay
+		 * control. */
+		plane_control =
+			EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg);
+		if ((plane_control & (3<<22)) != 0) {
+			plane_control &= ~(3<<22);
+			EMGD_WRITE32(plane_control,
+				MMIO(display) + PLANE(display)->plane_reg);
+			plane_start =
+				EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg + 4);
+			EMGD_WRITE32(plane_start,
+				MMIO(display) + PLANE(display)->plane_reg + 4);
+		}
+
+		/* Turn the overlay Off.
+		 * Ensure we are using the correct Pipe. */
+		pipe_num = PIPE(display)->pipe_num ?
+			(1<<24)/*Pipe B*/ :
+			(0<<24)/*Pipe A*/;
+		EMGD_WRITE32(pipe_num, MMIO(display) + 0x72180);
+		EMGD_WRITE32(0, MMIO(display) + 0x72184);
+
+		EMGD_TRACE_EXIT;
+		return IGD_SUCCESS;
+	}
+
+	/***********************************************************************
+	 * Copy the information passed in to the HW overlay structure
+	 **********************************************************************/
+	/* Zero the control, since they will be OR'ed in with data
+	 * below */
+	spritec_regs_plb->control = 0;
+
+	/* Interleaved/progressive and Odd/Even if interleaved */
+	if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+		EMGD_ERROR("Overlay2 does not support Interleaved");
+	}
+
+	/* Dest rect information */
+	EMGD_WRITE32((dest_rect->y1<<16) | (dest_rect->x1),
+		MMIO(display) + 0x7218C);
+	EMGD_WRITE32(((dest_rect->y2 - dest_rect->y1 - 1)<<16) |
+		(dest_rect->x2 - dest_rect->x1 - 1),
+		MMIO(display) + 0x72190);
+
+	/* Src rect and surface information */
+	ret = micro_spritec_update_src_plb(display, spritec_regs_plb, src_surf, src_rect);
+	if (ret) {
+		EMGD_ERROR_EXIT("Overlay2 updating src failed");
+		return ret;
+	}
+
+	/* Color control information */
+	if (!(flags & IGD_OVL_OSD_ON_SPRITEC)) {
+		ret = micro_spritec_update_video_quality_plb(display, src_surf,
+			&ovl_info->video_quality);
+		if (ret) {
+			EMGD_ERROR_EXIT("Overlay2 video quality failed");
+			return ret;
+		}
+		ret = micro_spritec_update_gamma_plb(display, spritec_regs_plb, &ovl_info->gamma);
+		if (ret) {
+			EMGD_ERROR("Overlay2 gamma failed");
+			return ret;
+		}
+	}
+
+	/* Destination color key */
+	EMGD_DEBUG("Color key.flags: 0x%lx", ovl_info->color_key.flags);
+	if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+		EMGD_DEBUG("Overlay Enable Dest Color Key");
+		/* The mask and color key are different for the different
+		 * pixel formats */
+		EMGD_WRITE32(convert_color_key_to_hw(
+					   PLANE(display)->fb_info->pixel_format,
+					   ovl_info->color_key.dest),
+			MMIO(display) + PLANE(display)->plane_reg + 0x14);
+		EMGD_WRITE32(convert_color_key_to_mask(
+					   PLANE(display)->fb_info->pixel_format,
+					   ovl_info->color_key.dest),
+			MMIO(display) + PLANE(display)->plane_reg + 0x18);
+
+		/* Both the plane control key enable and the second overlay
+		 * control order must be enabled to turn on destination color
+		 * key.  Also rewrite the plane_start which is the trigger for
+		 * Plane A/B */
+		plane_control =
+			EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg);
+		if ((plane_control & (3<<22)) != (3<<22)) {
+			plane_control |= (3<<22);
+			EMGD_WRITE32(plane_control,
+				MMIO(display) + PLANE(display)->plane_reg);
+			plane_start =
+				EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg + 4);
+			EMGD_WRITE32(plane_start,
+				MMIO(display) + PLANE(display)->plane_reg + 4);
+
+			/* Note: On a 915GM (maybe other platforms as well), the dest
+			 * color key is not always enabled when the plane A/B and
+			 * plane C are both modified in the same vblank.  So, ensure
+			 * they occur on a different vblank.  This should be fine,
+			 * since this will only occur the first time when enabling
+			 * the dest color key. */
+			display->context->dispatch.wait_vblank((igd_display_h)display);
+		}
+
+		if (flags & IGD_OVL_OSD_ON_SPRITEC) {
+			/* Sprite C should be below plane and above overlay. */
+			spritec_regs_plb->control |= 1;
+		} else {
+			/* Sprite C should be on the bottom of the Z order.
+			 * Plane B should be above Sprite C */
+			spritec_regs_plb->control |= 6;
+		}
+	} else {
+		EMGD_DEBUG("Overlay Disable Dest Color Key");
+		plane_control =
+			EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg);
+		if ((plane_control & (3<<22)) != 0) {
+			plane_control &= ~(3<<22);
+			EMGD_WRITE32(plane_control,
+				MMIO(display) + PLANE(display)->plane_reg);
+			plane_start =
+				EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg + 4);
+			EMGD_WRITE32(plane_start,
+				MMIO(display) + PLANE(display)->plane_reg + 4);
+		}
+	}
+
+	/* Source Color key */
+	if (ovl_info->color_key.flags & IGD_OVL_SRC_COLOR_KEY_ENABLE) {
+		EMGD_DEBUG("Overlay Enable Src Color Key");
+
+		ckey_high = convert_color_key_to_hw(src_surf->pixel_format,
+			ovl_info->color_key.src_hi);
+		ckey_high = yuv_to_uvy(src_surf->pixel_format,
+			ckey_high);
+
+		ckey_low = convert_color_key_to_hw(src_surf->pixel_format,
+			ovl_info->color_key.src_lo);
+		ckey_low = yuv_to_uvy(src_surf->pixel_format,
+			ckey_low);
+
+		EMGD_WRITE32(ckey_low,  MMIO(display) + 0x72194);
+		EMGD_WRITE32(ckey_high, MMIO(display) + 0x721a0);
+		EMGD_WRITE32(7,         MMIO(display) + 0x72198);
+		spritec_regs_plb->control |= (1<<22);
+	} else {
+		EMGD_DEBUG("Overlay Disable Src Color Key");
+		EMGD_WRITE32(0,         MMIO(display) + 0x72198);
+	}
+
+	/* General overlay information.  Turn the second overlay on.
+	 * The trigger register is the start register which causes the
+	 * overlay to update.  The trigger register is written in send_instr */
+	spritec_regs_plb->control |= (1<<31);
+    spritec_regs_plb->control |= PIPE(display)->pipe_num ?
+	    (1<<24)/*Pipe B*/ :
+	    (0<<24)/*Pipe A*/;
+    EMGD_WRITE32(spritec_regs_plb->control, MMIO(display) + 0x72180);
+	/*EMGD_WRITE32(ovl2_regs_plb->start,   MMIO(display) + 0x72184);*/
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+#else /* OVL_PLB_CACHE_QUICK_SWAP is enabled. */
+
+/* Poulsbo overlay cache structure */
+static ovl_plb_cache_t ovl_cache;
+
+/* Flag to signal the cache is invalid and needs
+ * to be re-initialized */
+static int ovl_cache_needs_init = TRUE;
+
+
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_update_src_ptr_plb()
+ *
+ * Description:
+ *   This function updates the source offset
+ *
+ * Returns:
+ *   != 0 on Error
+ *   0 on Success
+ *----------------------------------------------------------------------*/
+unsigned int micro_spritec_update_src_ptr_plb(igd_surface_t *src_surf,
+					  igd_rect_t    *src_rect)
+{
+	unsigned int      src_Bpp;
+
+	EMGD_TRACE_ENTER;
+
+	/* This is in Bytes per pixel */
+	src_Bpp = IGD_PF_BPP(src_surf->pixel_format) / 8;
+
+	/* src surface */
+	ovl_cache.ovl2_regs.start =
+		src_surf->offset +
+		(src_rect->y1 * src_surf->pitch) +
+		(src_rect->x1 * src_Bpp);
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_update_src_plb()
+ *
+ * Description:
+ *   This function updates the source pitch and pixel format
+ *
+ * Returns:
+ *   != 0 on Error
+ *   0 on Success
+ *----------------------------------------------------------------------*/
+unsigned int micro_spritec_update_src_plb(igd_surface_t *src_surf,
+					  igd_rect_t    *src_rect)
+{
+	EMGD_TRACE_ENTER;
+
+	ovl_cache.ovl2_regs.pitch = src_surf->pitch;
+
+	/* src pixel format */
+	switch(src_surf->pixel_format){
+	case IGD_PF_YUV422_PACKED_YUY2:
+		ovl_cache.ovl2_regs.control |= OVL2_CMD_YUV_422;
+		break;
+	case IGD_PF_YUV422_PACKED_UYVY:
+		ovl_cache.ovl2_regs.control |= OVL2_CMD_YUV_422 | OVL2_CMD_UYVY;
+		break;
+	case IGD_PF_ARGB32_8888:
+		ovl_cache.ovl2_regs.control |= OVL2_CMD_ARGB_8888;
+		break;
+	case IGD_PF_xRGB32_8888:
+		ovl_cache.ovl2_regs.control |= OVL2_CMD_RGB_8888;
+		break;
+	case IGD_PF_RGB16_565:
+		ovl_cache.ovl2_regs.control |= OVL2_CMD_RGB_565;
+		break;
+	case IGD_PF_xRGB16_555:
+	case IGD_PF_ARGB16_1555:
+		ovl_cache.ovl2_regs.control |= OVL2_CMD_RGB_555;
+		break;
+	case IGD_PF_ARGB8_INDEXED:
+		ovl_cache.ovl2_regs.control |= OVL2_CMD_RGB_8;
+		break;
+	default:
+		EMGD_ERROR_EXIT("Invalid pixel format: 0x%lx", src_surf->pixel_format);
+		return -IGD_ERROR_HWERROR;
+	}
+
+	/* Turn off YUV to RGB conversion if the src is RGB */
+	if (!(src_surf->pixel_format & PF_TYPE_YUV)) {
+		ovl_cache.ovl2_regs.control |= (1<<19);
+	}
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_update_video_quality_plb()
+ *
+ * Description:
+ *   This function updates the contrast, brightness, and saturation of
+ *   the overlay using the values specified in overlay_info.
+ *
+ * Returns:
+ *   != 0 on Error
+ *   0 on Success
+ *----------------------------------------------------------------------*/
+
+static int micro_spritec_update_video_quality_plb(
+	igd_surface_t                *src_surf,
+	igd_ovl_video_quality_info_t *video_quality)
+{
+	int                          calc_brightness_tmp = 0;
+	int                          calc_brightness     = 0;
+	unsigned int                 calc_contrast_tmp   = 0;
+	unsigned int                 calc_contrast       = 0;
+	unsigned int                 calc_saturation_tmp = 0;
+	unsigned int                 calc_saturation     = 0;
+
+	EMGD_TRACE_ENTER;
+
+	/* If the src_surf pixel format is RGB, then brightness, contrast,
+	 * and saturation should all be set to the exact default */
+	if (src_surf->pixel_format & PF_TYPE_RGB) {
+		if (video_quality->brightness != 0x8000) {
+			EMGD_DEBUG("RGB surfaces must set brightness to default");
+		}
+		if (video_quality->contrast != 0x8000) {
+			EMGD_DEBUG("RGB surfaces must set contrast to default");
+		}
+		if (video_quality->saturation != 0x8000) {
+			EMGD_DEBUG("RGB surfaces must set saturation to default");
+		}
+
+		ovl_cache.ovl2_regs.cont_bright = OVL2_RGB_COLOR_DEF_CONT_BRGHT;
+		ovl_cache.ovl2_regs.satn_hue =  OVL2_RGB_COLOR_DEF_SATN_HUE;
+
+		EMGD_TRACE_EXIT;
+		return IGD_SUCCESS;
+	}
+
+	/*************************************************************************
+	 * Brightness
+	 *************************************************************************/
+	if (0x8000 == video_quality->brightness) {
+		calc_brightness = MID_BRIGHTNESS_YUV;
+	} else if (video_quality->brightness < 0x8000) {
+		/*
+		 * we have here a brightness that is less than the default
+		 * mid point
+		 */
+		calc_brightness_tmp = 0x8000 - video_quality->brightness;
+		calc_brightness_tmp <<= 14;
+		calc_brightness_tmp /= 0x8000;
+		calc_brightness     = -128 - MID_BRIGHTNESS_YUV;
+		/*
+		 * more range if the midpoint is positive but less range
+		 * if midpoint is negative
+		 */
+
+		calc_brightness *= calc_brightness_tmp;
+		calc_brightness += BIT13;
+		calc_brightness >>= 14;
+
+		if (calc_brightness < -128) {
+			calc_brightness = -128;
+		}
+		if (calc_brightness > MID_BRIGHTNESS_YUV) {
+			calc_brightness = MID_BRIGHTNESS_YUV;
+		}
+	} else {
+		/*
+		 * we have here a brightness that is more than the default
+		 * mid point
+		 */
+		calc_brightness_tmp = video_quality->brightness - 0x8000;
+		calc_brightness_tmp <<= 14;
+		calc_brightness_tmp /= 0x8000;
+		calc_brightness     = 127 - MID_BRIGHTNESS_YUV;
+		/*
+		 * less range if the midpoint is positive but more range
+		 * if midpoint is negative
+		 */
+		calc_brightness *= calc_brightness_tmp;
+		calc_brightness += BIT13;
+		calc_brightness >>= 14;
+
+		if (calc_brightness > 127) {
+			calc_brightness = 127;
+		}
+		if (calc_brightness < MID_BRIGHTNESS_YUV) {
+			calc_brightness = MID_BRIGHTNESS_YUV;
+		}
+	}
+
+	ovl_cache.ovl2_regs.cont_bright =
+		(ovl_cache.ovl2_regs.cont_bright & 0xFFFFFF00) |
+		(calc_brightness & 0xFF);
+
+
+	/*************************************************************************
+	 * Contrast
+	 *************************************************************************/
+	if (0x8000 == video_quality->contrast ){
+		calc_contrast = MID_CONTRAST_YUV;
+	} else if (video_quality->contrast < 0x8000) {
+		/* we have here a contrast that is less than the
+		 * default mid point */
+		calc_contrast_tmp = video_quality->contrast;
+		calc_contrast_tmp <<= 12;
+		calc_contrast_tmp /= 0x8000;
+		calc_contrast     = MID_CONTRAST_YUV;
+		calc_contrast     *= calc_contrast_tmp;
+		calc_contrast     += BIT11;
+		calc_contrast     >>= 12;
+		if (calc_contrast > 0x3F) {
+			calc_contrast = 0x3F;
+		}
+	} else {
+		/* we have here a contrast that is more than the
+		 * default mid point */
+		calc_contrast_tmp = video_quality->contrast - 0x8000;
+		calc_contrast_tmp <<= 12;
+		calc_contrast_tmp /= 0x8000;
+		calc_contrast     = (0x1FF - MID_CONTRAST_YUV);
+		calc_contrast     *= calc_contrast_tmp;
+		calc_contrast     += BIT11;
+		calc_contrast     >>= 12;
+		calc_contrast     += MID_CONTRAST_YUV;
+		if (calc_contrast > 0x1FF) {
+			calc_contrast = 0x1FF;
+		}
+	}
+
+        ovl_cache.ovl2_regs.cont_bright =
+                (ovl_cache.ovl2_regs.cont_bright & 0xF803FFFF ) |
+                ((calc_contrast & 0x1FF) << 18);
+
+
+	/*************************************************************************
+	 * Saturation
+	 *************************************************************************/
+	if (video_quality->saturation == 0x8000) {
+		calc_saturation = MID_SATURATION_YUV;
+	} else if (video_quality->saturation < 0x8000) {
+		/* we have here a saturation that is less than the default
+		 * mid point */
+		calc_saturation_tmp = video_quality->saturation;
+		calc_saturation_tmp <<= 12;
+		calc_saturation_tmp /= 0x8000;
+		calc_saturation     = MID_SATURATION_YUV;
+		calc_saturation     *= calc_saturation_tmp;
+		calc_saturation     += BIT11;
+		calc_saturation     >>= 12;
+		if (calc_saturation > 0x7F) {
+			calc_saturation = 0x7F;
+		}
+	} else {
+		/* we have here a saturation that is more than the default
+		 * mid point*/
+		calc_saturation_tmp = video_quality->saturation - 0x8000;
+		calc_saturation_tmp <<= 12;
+		calc_saturation_tmp /= 0x8000;
+		calc_saturation     = (0x3FF - MID_SATURATION_YUV);
+		calc_saturation     *= calc_saturation_tmp;
+		calc_saturation     += BIT11;
+		calc_saturation     >>= 12;
+		calc_saturation     += MID_SATURATION_YUV;
+
+		if (calc_saturation > 0x3FF) {
+			calc_saturation = 0x3FF;
+		}
+	}
+
+        ovl_cache.ovl2_regs.satn_hue =
+                (ovl_cache.ovl2_regs.satn_hue & 0xFFFFFC00 ) |
+                (calc_saturation & 0x3FF);
+
+	/*************************************************************************
+	 * Hue
+	 *************************************************************************/
+	/* Hue is always set to the default value.  It is based on the saturation
+	 * value, and having a separate hue is of minimal value. */
+        ovl_cache.ovl2_regs.satn_hue =
+		(ovl_cache.ovl2_regs.satn_hue & 0xF800FFFF);
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+
+static const int gamma_reg_input[OVL2_TOTAL_GAMMA_REG] = {8, 16, 32, 64, 128, 192};
+static const int gamma_reg_offset[OVL2_TOTAL_GAMMA_REG] = {
+	OVL2_REG_ADDR_GAMMA0,
+	OVL2_REG_ADDR_GAMMA1,
+	OVL2_REG_ADDR_GAMMA2,
+	OVL2_REG_ADDR_GAMMA3,
+	OVL2_REG_ADDR_GAMMA4,
+	OVL2_REG_ADDR_GAMMA5
+};
+static const unsigned int gamma_def[OVL2_TOTAL_GAMMA_REG] = {
+	0x00080808,
+	0x00101010,
+	0x00202020,
+	0x00404040,
+	0x00808080,
+	0x00c0c0c0
+};
+
+/*-----------------------------------------------------------------------------
+ * Function: spritec_update_gamma_plb()
+ *
+ * Description:
+ *    This function sets the gamma correction values for the overlays.
+ *
+ * Returns:
+ *   != 0 on Error
+ *   IGD_SUCCESS on Success
+ *---------------------------------------------------------------------------*/
+static int micro_spritec_update_gamma_plb(
+	igd_display_context_t *display,
+	igd_ovl_gamma_info_t *ovl_gamma)
+{
+	unsigned int          new_gamma_red_24i_8f, new_gamma_green_24i_8f;
+	unsigned int          new_gamma_blue_24i_8f;
+	unsigned int          gamma_normal_r_24i_8f;
+	unsigned int          gamma_normal_g_24i_8f;
+	unsigned int          gamma_normal_b_24i_8f;
+	unsigned int          gamma_reg, gamma_reg_24i_8f;
+	unsigned int          i;
+
+	EMGD_TRACE_ENTER;
+
+	/* FIXME: The gamma values are re-written for every alter_ovl call.
+	 * This may cause issues or may be to slow?  If so, store the previous
+	 * values and only re-write when they change. */
+
+	/* If the overlay gamma is disabled or the display is an 8 bit mode
+	 * (second overay can not support gamma in an 8 bit mode),
+	 * set it to the default */
+	if (((ovl_gamma->flags&IGD_OVL_GAMMA_ENABLE)==IGD_OVL_GAMMA_DISABLE) ||
+	     (PLANE(display)->fb_info->pixel_format == IGD_PF_ARGB8_INDEXED)) {
+		for (i = 0; i < OVL2_TOTAL_GAMMA_REG; i++) {
+			/* program register */
+			ovl_cache.ovl2_regs.gamma_regs[i] = gamma_def[i];
+		}
+		EMGD_TRACE_EXIT;
+		return IGD_SUCCESS;
+	}
+
+	/* It is assumed that the input value is a 24-bit number */
+	new_gamma_red_24i_8f   = ovl_gamma->red;
+	new_gamma_green_24i_8f = ovl_gamma->green;
+	new_gamma_blue_24i_8f  = ovl_gamma->blue;
+
+	/*
+	 * Program RGB for each of the 6 gamma registers
+	 */
+
+	/* Since the OS_POW_FIX function can only take an integer base,
+	 * we need to normalize the result by gamma_normal_x
+	 */
+	gamma_normal_r_24i_8f =  OS_POW_FIX(255, (1<<16)/new_gamma_red_24i_8f);
+	gamma_normal_g_24i_8f =  OS_POW_FIX(255, (1<<16)/new_gamma_green_24i_8f);
+	gamma_normal_b_24i_8f =  OS_POW_FIX(255, (1<<16)/new_gamma_blue_24i_8f);
+
+	for( i = 0; i < OVL2_TOTAL_GAMMA_REG; i++ )
+	{
+		/* red */
+		gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+					      (1<<16)/new_gamma_red_24i_8f);
+		gamma_reg =
+			((255 * gamma_reg_24i_8f) / gamma_normal_r_24i_8f) << 16;
+
+		/* green */
+		gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+					      (1<<16)/new_gamma_green_24i_8f);
+		gamma_reg        |=
+			((255 * gamma_reg_24i_8f) / gamma_normal_g_24i_8f) << 8;
+
+		/* blue */
+		gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+					      (1<<16)/new_gamma_blue_24i_8f);
+		gamma_reg        |=
+			((255 * gamma_reg_24i_8f) / gamma_normal_b_24i_8f);
+
+		/* program register */
+		ovl_cache.ovl2_regs.gamma_regs[i] = gamma_reg;
+
+	}
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_disable_ovl_plb()
+ *
+ * Description:
+ * Write the registers needed to turn off the overlay.
+ *
+ * Returns:
+ *   != 0 on Error
+ *   0 on Success
+ *----------------------------------------------------------------------*/
+
+static unsigned int micro_spritec_disable_ovl_plb(
+	igd_display_context_t *display	)
+{
+	unsigned int pipe_num;
+	unsigned int plane_control, plane_start;
+
+	/* Turn off the plane control key enable and the second overlay
+	 * control. */
+	plane_control =
+		EMGD_READ32(MMIO(display) + PLANE(display)->plane_reg);
+	if ((plane_control & (3<<22)) != 0) {
+		plane_control &= ~(3<<22);
+		EMGD_WRITE32(plane_control,
+			   MMIO(display) + PLANE(display)->plane_reg);
+		plane_start =
+			EMGD_READ32(MMIO(display) +
+				  PLANE(display)->plane_reg + 4);
+		EMGD_WRITE32(plane_start,
+			   MMIO(display) + PLANE(display)->plane_reg + 4);
+	}
+
+	/* Turn the overlay Off.
+	 * Ensure we are using the correct Pipe. */
+	pipe_num = PIPE(display)->pipe_num ?
+		(1<<24)/*Pipe B*/ :
+		(0<<24)/*Pipe A*/;
+	EMGD_WRITE32(pipe_num, MMIO(display) + 0x72180);
+	EMGD_WRITE32(0, MMIO(display) + 0x72184);
+
+	return IGD_SUCCESS;
+}
+
+
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_clear_cache_plb()
+ *
+ * Description:
+ *
+ *----------------------------------------------------------------------*/
+
+static void micro_spritec_clear_cache_plb(
+        igd_display_context_t *display,
+	unsigned int           flags)
+{
+	/* Force every cache check to miss */
+	OS_MEMSET(&ovl_cache, 0, sizeof(ovl_plb_cache_t));
+
+	/* We just set our cached flags to 0, which might accidently
+	 * match up with "OFF" for some important incoming flag
+	 * bits, causing us to think we already handled them when
+	 * we didn't.  So set our cached flags to the exact
+	 * opposite of the incoming flags, which will force
+	 * us to test and handle every single bit, regardless
+	 * of whether it is on or off. */
+	ovl_cache.flags = ~flags;
+
+	/* init our cached registers */
+	ovl_cache.ovl2_regs.plane_control =
+		EMGD_READ32(MMIO(display) +
+			  PLANE(display)->plane_reg);
+	ovl_cache.ovl2_regs.plane_start =
+		EMGD_READ32(MMIO(display) +
+			  PLANE(display)->plane_reg + 4);
+
+	/* initialization complete */
+	ovl_cache_needs_init = FALSE;
+
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Function: spritec_update_colorkey_plb()
+ *
+ * Description:
+ *    This function sets the colorkey values for the overlays.
+ *
+ * Returns:
+ *   != 0 on Error
+ *   IGD_SUCCESS on Success
+ *---------------------------------------------------------------------------*/
+static void micro_spritec_update_colorkey_plb(
+	igd_display_context_t *display,
+	igd_surface_t         *src_surf,
+	igd_ovl_info_t        *ovl_info)
+{
+	unsigned int ckey_low, ckey_high;
+
+	/* Destination color key */
+	EMGD_DEBUG("Color key.flags: 0x%lx", ovl_info->color_key.flags);
+
+	if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+
+		EMGD_DEBUG("Overlay Enable Dest Color Key");
+		/* The mask and color key are different for the
+		 * different pixel formats */
+		ovl_cache.ovl2_regs.colorkey_hw =
+			convert_color_key_to_hw
+			(PLANE(display)->fb_info->pixel_format,
+			 ovl_info->color_key.dest);
+
+		ovl_cache.ovl2_regs.colorkey_mask =
+			convert_color_key_to_mask
+			(PLANE(display)->fb_info->pixel_format,
+			 ovl_info->color_key.dest);
+		/*
+		 * Both the plane control key enable and the second
+		 * overlay control order must be enabled to turn on
+		 * destination color key.  Also rewrite the
+		 * plane_start which is the trigger for Plane A/B
+		 */
+		if ( (ovl_cache.ovl2_regs.plane_control & (3<<22)) !=
+		     (3<<22)) {
+			ovl_cache.ovl2_regs.plane_control |= (3<<22);
+		}
+
+	} else {
+		EMGD_DEBUG("Overlay Disable Dest Color Key");
+		if ((ovl_cache.ovl2_regs.plane_control & (3<<22)) != 0) {
+			ovl_cache.ovl2_regs.plane_control &= ~(3<<22);
+		}
+	}
+
+	/* Source Color key */
+	if (ovl_info->color_key.flags & IGD_OVL_SRC_COLOR_KEY_ENABLE) {
+		EMGD_DEBUG("Overlay Enable Src Color Key");
+
+		ckey_high = convert_color_key_to_hw
+			(src_surf->pixel_format,
+			 ovl_info->color_key.src_hi);
+		ckey_high = yuv_to_uvy(src_surf->pixel_format,
+				       ckey_high);
+
+		ckey_low = convert_color_key_to_hw
+			(src_surf->pixel_format,
+			 ovl_info->color_key.src_lo);
+		ckey_low = yuv_to_uvy(src_surf->pixel_format,
+				      ckey_low);
+
+		ovl_cache.ovl2_regs.ckey_low = ckey_low;
+		ovl_cache.ovl2_regs.ckey_high = ckey_high;
+		ovl_cache.ovl2_regs.ckey_enable = 7;
+		ovl_cache.ovl2_regs.control |= (1<<22);
+	} else {
+		EMGD_DEBUG("Overlay Disable Src Color Key");
+		ovl_cache.ovl2_regs.ckey_enable = 0;
+	}
+
+}
+
+
+
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_write_cache_plb()
+ *
+ * Description:
+ *
+ *----------------------------------------------------------------------*/
+
+static void micro_spritec_write_cache_plb(
+        igd_display_context_t *display,
+	ovl2_reg_plb_t        *spritec_regs_plb,
+	igd_ovl_info_t        *ovl_info,
+	int                    cache_changed)
+{
+	int i;
+
+	/*
+	 * Now write all the changed registers to the HW
+	 * TODO: Or should we write all the registers, regardless of
+	 * if they have changed?
+	 * TODO: It may be beneficial to turn off overlay while
+	 * updateing the regs?
+	*/
+
+	/* Write source information */
+        if (cache_changed & (IGD_OVL_PLB_UPDATE_SURF |
+                             IGD_OVL_PLB_UPDATE_SRC  ) ) {
+		EMGD_WRITE32(ovl_cache.ovl2_regs.pitch,
+			   MMIO(display) + MMIO_OFFSET_PLB2_PITCH);
+	}
+
+	/* Write dest rect information */
+        if (cache_changed & IGD_OVL_PLB_UPDATE_DEST) {
+		EMGD_WRITE32( ovl_cache.ovl2_regs.dest_rect_x1y1,
+			    MMIO(display) + MMIO_OFFSET_PLB2_DEST_RECT_X1Y1);
+		EMGD_WRITE32( ovl_cache.ovl2_regs.dest_rect_x2y2,
+			    MMIO(display) + MMIO_OFFSET_PLB2_DEST_RECT_X2Y2);
+	}
+
+	/* write the quality information */
+        if (cache_changed & (IGD_OVL_PLB_UPDATE_VQ   |
+                             IGD_OVL_PLB_UPDATE_SURF ) ) {
+		EMGD_WRITE32(ovl_cache.ovl2_regs.cont_bright,
+			MMIO(display) + MMIO_OFFSET_PLB2_CONT_BRIGHT);
+		EMGD_WRITE32(ovl_cache.ovl2_regs.satn_hue,
+			MMIO(display) + MMIO_OFFSET_PLB2_SATN_HUE);
+	}
+
+	/* Write the gamma */
+        if (cache_changed & IGD_OVL_PLB_UPDATE_GAMMA) {
+		for (i = 0; i < OVL2_TOTAL_GAMMA_REG; i++) {
+			/* program register */
+			EMGD_WRITE32(ovl_cache.ovl2_regs.gamma_regs[i],
+				   MMIO(display) + gamma_reg_offset[i]);
+		}
+	}
+
+	/* Write the colorkey data */
+        if (cache_changed & IGD_OVL_PLB_UPDATE_COLORKEY) {
+
+		/* Dest color key */
+		if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+
+			/* Write the regs needed to turn it on */
+			EMGD_WRITE32(ovl_cache.ovl2_regs.colorkey_hw,
+				   MMIO(display) +
+				   PLANE(display)->plane_reg +
+				   MMIO_OFFSET_PLB2_COLORKEY_HW);
+
+			EMGD_WRITE32(ovl_cache.ovl2_regs.colorkey_mask,
+				   MMIO(display) +
+				   PLANE(display)->plane_reg +
+				   MMIO_OFFSET_PLB2_COLORKEY_MASK);
+		}
+
+		EMGD_WRITE32(ovl_cache.ovl2_regs.plane_control,
+			   MMIO(display) + PLANE(display)->plane_reg);
+
+		EMGD_WRITE32(ovl_cache.ovl2_regs.plane_start,
+			   MMIO(display) + PLANE(display)->plane_reg+4);
+
+		/*
+		 * Note: On a 915GM (maybe other platforms as well),
+		 * the dest color key is not always enabled when the
+		 * plane A/B and plane C are both modified in the
+		 * same vblank.  So, ensure they occur on a different
+		 * vblank.  This should be fine, since this will only
+		 * occur the first time when enabling the dest color
+		 * key.
+		 */
+		if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+			display->context->dispatch.
+				wait_vblank((igd_display_h)display);
+		}
+
+		/* Source Color key */
+		if (ovl_info->color_key.flags & IGD_OVL_SRC_COLOR_KEY_ENABLE) {
+			EMGD_WRITE32(ovl_cache.ovl2_regs.ckey_low,
+				   MMIO(display) + MMIO_OFFSET_PLB2_CKEY_LOW);
+			EMGD_WRITE32(ovl_cache.ovl2_regs.ckey_high,
+				   MMIO(display) + MMIO_OFFSET_PLB2_CKEY_HIGH);
+		}
+
+		EMGD_WRITE32(ovl_cache.ovl2_regs.ckey_enable,
+			   MMIO(display) + MMIO_OFFSET_PLB2_CKEY_ENABLE);
+	}
+
+	/* Write the control register, but not the start register.
+	   The trigger register is the start register
+	   which causes the overlay to update.  The trigger
+	   register is written in send_instr */
+
+	EMGD_WRITE32(ovl_cache.ovl2_regs.control,
+		   MMIO(display) + MMIO_OFFSET_PLB2_CONTROL);
+
+	spritec_regs_plb->start = ovl_cache.ovl2_regs.start;
+	spritec_regs_plb->control = ovl_cache.ovl2_regs.control;
+
+}
+
+
+
+
+
+/*----------------------------------------------------------------------
+ * Function: micro_spritec_update_regs_plb()
+ *
+ * Description:
+ * Examine the incoming overlay parameters, and update the overlay hardware
+ * regs according to what changed.
+ *
+ * Returns:
+ *   != 0 on Error
+ *   0 on Success
+ *----------------------------------------------------------------------*/
+
+static unsigned int micro_spritec_update_regs_plb(
+	igd_display_context_t *display,
+	ovl2_reg_plb_t      *spritec_regs_plb,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	igd_ovl_info_t      *ovl_info,
+	unsigned int         flags)
+{
+	// unsigned int ckey_low, ckey_high;
+	// int i,
+	int ret;
+	int cache_changed;
+
+
+	EMGD_TRACE_ENTER;
+
+	/* Fast path for turning off overlay. No need for cache */
+	if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+		ret = micro_spritec_disable_ovl_plb(display);
+
+		/* Reset the cache */
+		ovl_cache_needs_init = TRUE;
+
+		return ret;
+	}
+
+	/* Init the cache if needed */
+	if (ovl_cache_needs_init) {
+		micro_spritec_clear_cache_plb(display, flags);
+	}
+
+	/* See what has changed in the cache */
+        cache_changed = get_cache_changes_plb (src_surf,
+					   src_rect,
+					   dest_rect,
+					   ovl_info,
+					   flags,
+					   &ovl_cache);
+
+	/*
+	 * Perhaps the biggest challenge of caching the overlay
+         * state is what to do with the command and config regs.
+         * Normally we would clear command and config to 0 here,
+         * and let the update process set only the bits that are
+         * needed.  But doing this would invalidate our cache.
+         * Instead we are relying on the above call to
+         * get_cache_changes() to clear those bits in command
+         * and config that will be changing */
+
+
+	/* Normally we would set interleave parameters here,
+	 * but the secondary overlay does not support interleave.*/
+	if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+		EMGD_ERROR("Overlay2 does not support Interleaved");
+	}
+
+	/* ----------------------------------------------------------*/
+        /* Has our destination rectangle changed? */
+        if (cache_changed & IGD_OVL_PLB_UPDATE_DEST) {
+
+		ovl_cache.ovl2_regs.dest_rect_x1y1 =
+			( (dest_rect->y1 << 16) | dest_rect->x1 );
+		ovl_cache.ovl2_regs.dest_rect_x2y2 =
+			( (dest_rect->y2 - dest_rect->y1 - 1) << 16) |
+		 	  (dest_rect->x2 - dest_rect->x1 - 1)        ;
+	}
+
+	/* ----------------------------------------------------------*/
+        /* Always update the source pointers every frame. */
+	ret = micro_spritec_update_src_ptr_plb(src_surf,
+					   src_rect);
+	if (ret) {
+		EMGD_ERROR_EXIT("Overlay2 updating src failed");
+		return ret;
+	}
+
+
+	/* ----------------------------------------------------------*/
+        /* Did either the Src rect or surface change? */
+        if (cache_changed & (IGD_OVL_PLB_UPDATE_SURF |
+                             IGD_OVL_PLB_UPDATE_SRC  ) ) {
+		ret = micro_spritec_update_src_plb(src_surf,
+						   src_rect);
+		if (ret) {
+			EMGD_ERROR_EXIT("Overlay2 updating src failed");
+			return ret;
+		}
+	}
+
+	/* ----------------------------------------------------------*/
+	/* Did the quality information change? */
+        if (cache_changed & (IGD_OVL_PLB_UPDATE_VQ   |
+                             IGD_OVL_PLB_UPDATE_SURF ) ) {
+		ret = micro_spritec_update_video_quality_plb
+			(src_surf,
+			 &ovl_info->video_quality);
+		if (ret) {
+			EMGD_ERROR_EXIT("Overlay2 video quality failed");
+			return ret;
+		}
+	}
+
+	/* ----------------------------------------------------------*/
+	/* Did the gamma change? */
+        if (cache_changed & IGD_OVL_PLB_UPDATE_GAMMA) {
+		ret = micro_spritec_update_gamma_plb(display, &ovl_info->gamma);
+		if (ret) {
+			EMGD_ERROR("Overlay2 gamma failed");
+			return ret;
+		}
+
+	}
+
+	/* ----------------------------------------------------------*/
+	/* Did the color key change? */
+        if (cache_changed & IGD_OVL_PLB_UPDATE_COLORKEY) {
+		micro_spritec_update_colorkey_plb(display,
+						  src_surf,
+						  ovl_info);
+	}
+
+	if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+		if (flags & IGD_OVL_OSD_ON_SPRITEC) {
+			ovl_cache.ovl2_regs.control |= 1;
+		} else {
+			/* Sprite C should be on the bottom of the Z order.
+			 * Plane B should be above Sprite C */
+			ovl_cache.ovl2_regs.control |= 6;
+		}
+	}
+
+	/* General overlay information.  Turn the second overlay on. */
+	ovl_cache.ovl2_regs.control |= (1<<31);
+	ovl_cache.ovl2_regs.control |= PIPE(display)->pipe_num ?
+		(1<<24)/*Pipe B*/ :
+		(0<<24)/*Pipe A*/;
+
+	/*
+	 * Now write all the changes to the part
+	 */
+	micro_spritec_write_cache_plb(display,
+				      spritec_regs_plb,
+				      ovl_info,
+				      cache_changed);
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+#endif
+
+
+
+unsigned int micro_spritec_send_instr_plb(
+	igd_display_context_t     *display,
+	ovl2_reg_plb_t    *spritec_regs_plb,
+	unsigned int      flags)
+{
+	EMGD_TRACE_ENTER;
+
+	/* Send a load register instruction to write the Plane C sprite address
+	 * which is the trigger register.
+	 * This is an instruction, so it happens after blend, and since it
+	 * is an instruction, we do not have to poll waiting for it. */
+
+#ifdef OVL_PLB_CACHE_QUICK_SWAP /* If caching is enabled */
+	EMGD_WRITE32(ovl_cache.ovl2_regs.start, MMIO(display) +
+		   MMIO_OFFSET_PLB2_START);
+
+#else
+	EMGD_WRITE32(spritec_regs_plb->start, MMIO(display) + 0x72184);
+#endif
+
+	ovl_context->sync2 = 0;
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+int micro_prepare_ovl2_plb(
+	igd_display_context_t *display,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	igd_ovl_info_t      *ovl_info,
+	ovl2_reg_plb_t      *spritec_regs_plb,
+	unsigned int         flags)
+{
+	int ret = 0;
+
+	EMGD_TRACE_ENTER;
+
+	/* Check to ensure the overlay can be used given the current mode as
+	 * well as what the IAL is asking for.  If not return an error. */
+
+	if( (OVL2_CHECK_PLB_RET(ret,display, src_surf, src_rect,
+				dest_rect, ovl_info,flags)) ) {
+		if (ret) {
+			EMGD_ERROR_EXIT("Overlay2 Check failed");
+			return ret;
+		}
+	}
+
+	/* Check if last flip is still pending.
+	 * This is necessary for the following reasons:
+	 *    - If the previous instructions have not been processed, then the
+	 *      spritec_regs_plb is still in use and can not be overwritten.
+	 */
+	if (PIPE(display)){
+		if( (QUERY_OVL2_PLB_RET(ret,(igd_display_h)display,
+								IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE)) ){
+			if ((FALSE == ret) &&
+				(flags & IGD_OVL_ALTER_ON)) {
+				/* Only return an error if the overlay is on.  If turning it off,
+				* allow it to continue, since something may have failed and we
+				* should try our best to turn the overlay off. */
+				return -IGD_ERROR_HWERROR;
+			}
+		}
+	}
+
+	/* Update all Overlay Update Registers */
+	ret = micro_spritec_update_regs_plb(display, spritec_regs_plb,
+		src_surf, src_rect, dest_rect, ovl_info,
+		flags);
+	if (ret) {
+		EMGD_ERROR_EXIT("Sprite C update Registers failed");
+		return ret;
+	}
+
+	EMGD_TRACE_EXIT;
+	return ret;
+}
+
+
+
+int micro_alter_ovl2_plb(igd_display_context_t *display,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	igd_ovl_info_t      *ovl_info,
+	unsigned int         flags)
+{
+	ovl2_reg_plb_t spritec_regs_plb;
+	int ret=0;
+
+	EMGD_TRACE_ENTER;
+
+	/* Dump overlay parameters for debugging */
+	/*
+	if (src_surf && src_rect && dest_rect && ovl_info) {
+		printk (KERN_ERR " micro_alter_ovl2_plb  Entry."
+			"offset=0x%X "
+			"pitch=%d "
+			"width=%d "
+			"height=%d \n"
+			"pixel_format=0x%X "
+			"flags=0x%X "
+			"virt_addr=0x%X "
+			"pvr2d_mem_info=0x%X "
+			"pvr2d_context_h=0x%X "
+			"hPVR2DFlipChain=0x%X \n"
+			"src_x1=%d "
+			"src_x2=%d "
+			"src_y1=%d "
+			"src_y2=%d "
+			"src width=%d "
+			"src height=%d \n"
+			"dest_x1=%d "
+			"dest_x2=%d "
+			"dest_y1=%d "
+			"dest_y2=%d "
+			"dest width=%d "
+			"dest height=%d \n"
+			"color_key.src_lo=0x%X "
+			"color_key.src_hi=0x%X "
+			"color_key.dest=0x%X "
+			"color_key.flags=0x%X "
+			"flags=0x%X "
+			,
+			(unsigned int) src_surf->offset ,
+			(unsigned int) src_surf->pitch ,
+			(unsigned int) src_surf->width ,
+			(unsigned int) src_surf->height ,
+			(unsigned int) src_surf->pixel_format ,
+			(unsigned int) src_surf->flags ,
+			(unsigned int) src_surf->virt_addr ,
+			(unsigned int) src_surf->pvr2d_mem_info ,
+			(unsigned int) src_surf->pvr2d_context_h ,
+			(unsigned int) src_surf->hPVR2DFlipChain ,
+			(unsigned int) src_rect->x1,
+			(unsigned int) src_rect->x2,
+			(unsigned int) src_rect->y1,
+			(unsigned int) src_rect->y2,
+			(unsigned int) (src_rect->x2 - src_rect->x1),
+			(unsigned int) (src_rect->y2 - src_rect->y1),
+			(unsigned int) dest_rect->x1,
+			(unsigned int) dest_rect->x2,
+			(unsigned int) dest_rect->y1,
+			(unsigned int) dest_rect->y2,
+			(unsigned int) (dest_rect->x2 - dest_rect->x1),
+			(unsigned int) (dest_rect->y2 - dest_rect->y1),
+			(unsigned int) ovl_info->color_key.src_lo,
+			(unsigned int) ovl_info->color_key.src_hi,
+			(unsigned int) ovl_info->color_key.dest,
+			(unsigned int) ovl_info->color_key.flags,
+			(unsigned int) flags
+			);
+	}
+	*/
+	/* Initialize structure so compilers don't complain */
+	OS_MEMSET(&spritec_regs_plb, 0, sizeof(ovl2_reg_plb_t));
+
+	if (micro_prepare_ovl2_plb(display, src_surf, src_rect, dest_rect,
+		ovl_info, &spritec_regs_plb, flags)) {
+		return -IGD_ERROR_HWERROR;
+	}
+
+	/* Directlt write the register to update 2nd overlay */
+	ret = micro_spritec_send_instr_plb(display, &spritec_regs_plb, flags);
+
+	EMGD_TRACE_EXIT;
+	return ret;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.c b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.c
new file mode 100644
index 0000000..816c3ab
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.c
@@ -0,0 +1,542 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl2_plb.c
+ * $Revision: 1.22 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains function that actually programs the second
+ *  overlay with the bits to properly configure the overlay
+ *  Also includes functions to execute the second overlay flip
+ *  instruction, and query the overlay flip status.
+ *  Also contains some hardware capabilities querrying functions
+ *  for upper overlay layer to get this chips second overlay
+ *  capabilities
+ *-----------------------------------------------------------------------------
+ */
+/* Referenced from Napa. Need change later */
+
+#define MODULE_NAME hal.overlay
+
+#include "ovl_plb_cache.h"
+#include <plb/regs.h>
+#include <plb/cmd.h>
+#include <plb/context.h>
+#include "../cmn/ovl_dispatch.h"
+#include "../cmn/ovl_virt.h"
+#include "ovl2_regs_plb.h"
+
+extern unsigned long sprite_pixel_formats_plb[];
+extern int micro_prepare_ovl2_plb(
+	igd_display_context_t *display,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	igd_ovl_info_t      *ovl_info,
+	ovl2_reg_plb_t      *spritec_regs_plb,
+	unsigned int         flags);
+
+/*----------------------------------------------------------------------
+ * Function: ovl2_check_pf_plb()
+ * Parameters: unsigned int requested_pixel_format -
+ *             according to definitions in igd_mode.h
+ *
+ * Description:
+ *
+ * Returns:
+ *   TRUE on Success
+ *   FALSE on The first pixel format that is supported
+ *----------------------------------------------------------------------*/
+static unsigned int ovl2_check_pf_plb(
+	igd_display_context_t *display,
+	unsigned int requested_pixel_format)
+{
+	unsigned long *spr_pf = sprite_pixel_formats_plb;
+	int temp_loop = 0;
+
+	while(spr_pf[temp_loop]) {
+		if(spr_pf[temp_loop] == requested_pixel_format) {
+			return TRUE;
+		}
+		++temp_loop;
+	}
+
+	return FALSE;
+}
+
+static unsigned int get_uv_shift_x (unsigned long pf)
+{
+
+	switch(pf) {
+	case IGD_PF_YUV422_PACKED_YUY2:
+	case IGD_PF_YUV422_PACKED_UYVY:
+	case IGD_PF_YUV420_PLANAR_I420: /* same as IYUV */
+	case IGD_PF_YUV420_PLANAR_YV12:
+	case IGD_PF_YUV420_PLANAR_NV12:
+		return 1;
+		break;
+	case IGD_PF_YUV410_PLANAR_YVU9:
+		return 2;
+		break;
+	default:
+		return 0;
+	}
+
+}
+
+static unsigned int get_uv_shift_y (unsigned long pf)
+{
+
+	switch(pf) {
+	case IGD_PF_YUV420_PLANAR_I420: /* same as IYUV */
+	case IGD_PF_YUV420_PLANAR_YV12:
+	case IGD_PF_YUV420_PLANAR_NV12:
+		return 1;
+		break;
+	case IGD_PF_YUV410_PLANAR_YVU9:
+		return 2;
+		break;
+	default:
+		return 0;
+	}
+
+}
+
+unsigned int ovl2_check_plb(igd_display_context_t *display,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	igd_ovl_info_t      *ovl_info,
+	unsigned int         flags)
+{
+	igd_timing_info_t *timing;
+	unsigned int min_w, min_h;
+
+	EMGD_TRACE_ENTER;
+
+	if (!display){
+		EMGD_ERROR_EXIT("display is null");
+	    return -IGD_ERROR_INVAL;
+	}
+	if (!PIPE(display)){
+	    EMGD_ERROR_EXIT("PIPE(display) is null");
+	    return -IGD_ERROR_INVAL;
+	}
+
+	timing = PIPE(display)->timing;
+
+    if(!timing) {
+        EMGD_ERROR_EXIT("timing is null\n");
+        return -IGD_ERROR_INVAL;
+    }
+
+	/* The following parameters are only valid if the overlay is on, so
+	 * return success if the overlay is being turned off. */
+	if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+		EMGD_TRACE_EXIT;
+		return IGD_SUCCESS;
+	}
+
+	/*************************************************************************
+	 * Ensure the framebuffer dotclock does not exceed the board SKU
+	 * max dotclock
+	 **************************************************************************/
+        /* Make it chipset-specific */
+        /* DCT-PC99TA crashes with dotclock > 300MHz */
+	if(timing->dclk >= 340000){
+		EMGD_ERROR_EXIT("Cannot support dotclock > 340MHz for this SKU");
+		return -IGD_ERROR_HWERROR;
+	}
+
+	/*************************************************************************
+	 * Ensure the overlay surface is ok and can be properly displayed.
+	 * This ensures the following is valid:
+	 *    - Ensure x1, x2, y1, y2 are pixel aligned
+	 *    - 2 pixels or greater in width and height
+	 *    - Pixel format is supported by the overlay
+	 *    - Pitch is <= 8KB
+	 *    - Based on the pixel format, the width is supported
+	 *************************************************************************/
+	if (!src_surf){
+		EMGD_ERROR_EXIT("src_surf is null");
+		return -IGD_ERROR_INVAL;
+	}
+	if (!src_rect){
+		EMGD_ERROR_EXIT("src_rect is null");
+		return -IGD_ERROR_INVAL;
+	}
+	/* Get the minimum size of 1 pixel in width and height for y, u, and v.
+	 */
+	min_w = 1 << get_uv_shift_x(src_surf->pixel_format);
+	min_h = 1 << get_uv_shift_y(src_surf->pixel_format);
+
+	if (((src_rect->x2 - src_rect->x1) < min_w*2) ||
+		((src_rect->y2 - src_rect->y1) < min_h*2)) {
+		EMGD_ERROR_EXIT(
+			"Overlay2 source width or height is < 2 pixels (%dx%d)\n",
+			src_rect->x2 - src_rect->x1, src_rect->y2 - src_rect->y1);
+		return -IGD_ERROR_INVAL;
+	}
+
+	if (FALSE == ovl2_check_pf_plb(display, src_surf->pixel_format)) {
+		EMGD_ERROR_EXIT("Overlay2 source pixel format unsupported (pf:0x%lx)",
+			src_surf->pixel_format);
+		return -IGD_ERROR_HWERROR;
+	}
+
+	if (src_surf->pitch > 8192) {
+		EMGD_ERROR_EXIT("Overlay2 source pitch (%d) > 8KB",
+			src_surf->pitch);
+		return -IGD_ERROR_HWERROR;
+	}
+
+	/*************************************************************************
+	 * Ensure the location on the framebuffer is ok and can be properly
+	 * displayed
+	 * This ensures the following is valid:
+	 *    - Greater than 1 pixel width and height
+	 *    - Will be displayed on screen (not panned off)
+	 *************************************************************************/
+	if (!dest_rect){
+		EMGD_ERROR_EXIT("dest_rect is null");
+		return -IGD_ERROR_INVAL;
+	}
+	if (((dest_rect->x2 - dest_rect->x1) <= 1) ||
+		((dest_rect->y2 - dest_rect->y1) <= 1)) {
+		EMGD_ERROR_EXIT(
+			"Overlay2 dest width or height is single pixel (%dx%d)\n",
+			dest_rect->x2 - dest_rect->x1, dest_rect->y2 - dest_rect->y1);
+		return -IGD_ERROR_INVAL;
+	}
+
+	if ((dest_rect->x1 >= timing->width) ||
+		(dest_rect->y1 >= timing->height)) {
+		EMGD_ERROR_EXIT(
+			"Overlay2 dest is panned off the screen (%d,%d)\n",
+			dest_rect->x1, dest_rect->y1);
+		return -IGD_ERROR_INVAL;
+	}
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+unsigned int ovl2_send_instr_plb(
+	igd_display_context_t     *display,
+	ovl2_reg_plb_t    *spritec_regs_plb,
+	unsigned int      flags)
+{
+	unsigned char * mmio = MMIO(display);
+	unsigned long tmp;
+	inter_module_dispatch_t *md;
+	platform_context_plb_t * platform;
+	unsigned int pipe_num;
+	unsigned long pipe_reg;
+	int ret;
+
+	EMGD_TRACE_ENTER;
+
+	/* We dont need the CMD_WAIT_OVL2_PLB instruction coz
+	 * our alter_ovl code already querried status
+	 * for last flip completion before getting here. See
+	 * micro_prepare_ovl2_plb called by alter_ovl2_plb.
+	 * It calls query overlay before the next flip
+	 */
+
+
+	/*
+	 * If Overlay + FB Blend is requested and the FB is xRGB
+	 * turn on the ARGB format.
+	 */
+	if(ovl_context->fb_blend_ovl) {
+		if ((flags & IGD_OVL_ALTER_ON) != IGD_OVL_ALTER_ON) {
+			tmp = EMGD_READ32(mmio +  PLANE(display)->plane_reg);
+			if((tmp & 0x3c000000) == 0x1c000000) {
+				tmp = tmp & 0xc3FFFFFF;
+				EMGD_WRITE32(tmp | 0x18000000, mmio +  PLANE(display)->plane_reg);
+				tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 4);
+				EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 4);
+				OS_SLEEP(100);
+			}
+		} else {
+			tmp = EMGD_READ32(mmio +  PLANE(display)->plane_reg);
+			if((tmp & 0x3c000000) == 0x18000000) {
+				EMGD_WRITE32(tmp | 0x1c000000, mmio +  PLANE(display)->plane_reg);
+				tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 4);
+				EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 4);
+			}
+		}
+	}
+
+
+	/* Send a load register instruction to write the Plane C sprite address
+	 * which is the trigger register.
+	 * This is an instruction, so it happens after blend, and since it
+	 * is an instruction, we do not have to poll waiting for it. */
+	EMGD_WRITE32(spritec_regs_plb->start, mmio + 0x72184);
+
+	md = &display->context->mod_dispatch;
+	platform = (platform_context_plb_t *)display->context->
+			platform_context;
+
+	pipe_num = PIPE(display)->pipe_num;
+
+	if(pipe_num){
+		pipe_reg = 0x71024;
+	} else {
+		pipe_reg = 0x70024;
+	}
+
+        if(md && md->set_flip_pending){
+                /* For second overlay, Poulsbo has no ISR bit
+	         * to reflect the flip pending for Display
+                 * Sprite C. So we use Pipe-B vblank status
+                 * as a substitute
+                 */
+                ret = OS_PTHREAD_MUTEX_LOCK(&platform->flip_mutex);
+                md->set_flip_pending(MMIO(display), pipe_reg);
+                OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex);
+        }
+
+	ovl_context->sync2 = 0;
+
+	display->context->dispatch.sync(display,
+		IGD_PRIORITY_NORMAL,
+		&ovl_context->sync2,
+		IGD_SYNC_NONBLOCK);
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+int alter_ovl2_plb(igd_display_context_t *display,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	igd_ovl_info_t      *ovl_info,
+	unsigned int         flags)
+{
+	ovl2_reg_plb_t spritec_regs_plb;
+	int ret=0;
+
+	EMGD_TRACE_ENTER;
+
+	/* Dump overlay parameters for debugging */
+	/*
+	if (src_surf && src_rect && dest_rect && ovl_info) {
+		printk (KERN_ERR " alter_ovl2_plb  Entry."
+			"offset=0x%X "
+			"pitch=%d "
+			"width=%d "
+			"height=%d \n"
+			"pixel_format=0x%X "
+			"flags=0x%X "
+			"virt_addr=0x%X "
+			"pvr2d_mem_info=0x%X "
+			"pvr2d_context_h=0x%X "
+			"hPVR2DFlipChain=0x%X \n"
+			"src_x1=%d "
+			"src_x2=%d "
+			"src_y1=%d "
+			"src_y2=%d "
+			"src width=%d "
+			"src height=%d \n"
+			"dest_x1=%d "
+			"dest_x2=%d "
+			"dest_y1=%d "
+			"dest_y2=%d "
+			"dest width=%d "
+			"dest height=%d \n"
+			"color_key.src_lo=0x%X "
+			"color_key.src_hi=0x%X "
+			"color_key.dest=0x%X "
+			"color_key.flags=0x%X "
+			"flags=0x%X "
+			,
+			(unsigned int) src_surf->offset ,
+			(unsigned int) src_surf->pitch ,
+			(unsigned int) src_surf->width ,
+			(unsigned int) src_surf->height ,
+			(unsigned int) src_surf->pixel_format ,
+			(unsigned int) src_surf->flags ,
+			(unsigned int) src_surf->virt_addr ,
+			(unsigned int) src_surf->pvr2d_mem_info ,
+			(unsigned int) src_surf->pvr2d_context_h ,
+			(unsigned int) src_surf->hPVR2DFlipChain ,
+			(unsigned int) src_rect->x1,
+			(unsigned int) src_rect->x2,
+			(unsigned int) src_rect->y1,
+			(unsigned int) src_rect->y2,
+			(unsigned int) (src_rect->x2 - src_rect->x1),
+			(unsigned int) (src_rect->y2 - src_rect->y1),
+			(unsigned int) dest_rect->x1,
+			(unsigned int) dest_rect->x2,
+			(unsigned int) dest_rect->y1,
+			(unsigned int) dest_rect->y2,
+			(unsigned int) (dest_rect->x2 - dest_rect->x1),
+			(unsigned int) (dest_rect->y2 - dest_rect->y1),
+			(unsigned int) ovl_info->color_key.src_lo,
+			(unsigned int) ovl_info->color_key.src_hi,
+			(unsigned int) ovl_info->color_key.dest,
+			(unsigned int) ovl_info->color_key.flags,
+			(unsigned int) flags
+			);
+	}
+	*/
+	/* Initialize structure so compilers don't complain */
+	OS_MEMSET(&spritec_regs_plb, 0, sizeof(ovl2_reg_plb_t));
+
+	if (micro_prepare_ovl2_plb(display, src_surf, src_rect, dest_rect,
+		ovl_info, &spritec_regs_plb, flags)) {
+		return -IGD_ERROR_HWERROR;
+	}
+
+	/* Send the instructions to the command queue */
+	ret = ovl2_send_instr_plb(display, &spritec_regs_plb, flags);
+
+	EMGD_TRACE_EXIT;
+	return ret;
+}
+
+int query_ovl2_plb(igd_display_h display_h,
+	unsigned int flags)
+{
+	igd_display_context_t *display = (igd_display_context_t *)display_h;
+	inter_module_dispatch_t *md;
+	platform_context_plb_t * platform;
+	os_alarm_t timeout;
+	int ret;
+	unsigned int pipe_num;
+	unsigned long pipe_reg;
+
+	EMGD_TRACE_ENTER;
+
+	switch (flags) {
+	case IGD_OVL_QUERY_IS_HW_SUPPORTED:
+		/* This is the second overlay, so HW overlay is not supported */
+		break;
+
+	case IGD_OVL_QUERY_IS_LAST_FLIP_DONE:
+		/* If there no sync to wait on, then the last flip is done, and the
+		 * Register Update has occured, simply return TRUE (Flip done).
+		 */
+		/*if (!ovl_context->sync2) {
+			EMGD_DEBUG("Overlay already synced");
+			EMGD_TRACE_EXIT;
+			return TRUE;
+		}*/
+
+		/* Wait for vblank */
+		/* Check to see if the plane C flip is pending.  If is is pending
+		 * return FALSE (Flip not done). */
+		/*if(display->context->dispatch.sync(
+			display,
+			IGD_PRIORITY_NORMAL,
+			&ovl_context->sync2,
+			IGD_SYNC_NONBLOCK)) {
+			EMGD_DEBUG("Overlay Sync Check - Flip not done");
+			return FALSE;
+		}*/
+		/* According to the PBL B-spec, there doesnt seem to exist any bit
+		 * for Sprite C Flip-Pending status. Testing 0x20AC in code during
+		 * virt queue's REG write shows nothing changed for Bit8. Thus, we
+		 * are using state of the VBLANK ISR bit as ovl2 flip status.
+		 * Assumption is that if were running 2nd overlay, its either clone
+		 * display or VEXT in WinCE. In either case, were not doing full screen
+		 * FB flipping, so this check should be 'statefully' accurate
+		 */
+
+		if (PIPE(display)){
+			pipe_num = PIPE(display)->pipe_num;
+
+			if(pipe_num){
+				pipe_reg = 0x71024;
+			} else {
+				pipe_reg = 0x70024;
+			}
+
+			md = &display->context->mod_dispatch;
+			platform = (platform_context_plb_t *)display->context->
+						platform_context;
+			if(md && md->check_flip_pending){
+				ret = OS_PTHREAD_MUTEX_LOCK(&platform->flip_mutex);
+				if(md->check_flip_pending(MMIO(display), pipe_reg)){
+					OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex);
+					EMGD_DEBUG("Overlay2 Sync done but Flip not done");
+					return FALSE;
+				}
+				OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex);
+			}
+
+		} else {
+			EMGD_TRACE_EXIT;
+			return TRUE;
+		}
+		/* Now that we know the last flip is done and the register update is
+		 * complete, set the sync to 0 and return TRUE (Flip done). */
+		ovl_context->sync2 = 0;
+		break;
+	case IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE:
+		/* Wait for 200 milliseconds for the last flip to complete.  If not
+		 * done in that time, there is likely a hardware problem so return
+		 * FALSE. */
+		timeout = OS_SET_ALARM(200);
+		do {
+			if (TRUE ==
+				query_ovl2_plb(display_h, IGD_OVL_QUERY_IS_LAST_FLIP_DONE)) {
+				EMGD_TRACE_EXIT;
+				return TRUE;
+			}
+		} while (!OS_TEST_ALARM(timeout));
+		EMGD_ERROR_EXIT("Timeout waiting for last flip done");
+		return FALSE;
+		break;
+	case IGD_OVL_QUERY_IS_GAMMA_SUPPORTED:
+		return TRUE;
+		break;
+	case IGD_OVL_QUERY_IS_VIDEO_PARAM_SUPPORTED:
+		return TRUE;
+		break;
+	}
+
+	EMGD_TRACE_EXIT;
+	return TRUE;
+}
+
+
+
+int query_max_size_ovl2_plb(
+	igd_display_h display_h,
+	unsigned long pf,
+	unsigned int *max_width,
+	unsigned int *max_height)
+{
+	EMGD_TRACE_ENTER;
+
+	/* FIXME: Should this be size of FB? */
+	*max_width = 2048;
+	*max_height = 2048;
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.h b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.h
new file mode 100644
index 0000000..dca46bc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_plb.h
@@ -0,0 +1,55 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl2_plb.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the internal header file for napa overlay engine. It should be not be
+ *  by any other module besides the overlay module itself. It contains the
+ *  neccessary hardware virtualized structures and functions internal to
+ *  the napa core's overlay engine
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _OVL2_PLB_H
+#define _OVL2_PLB_H
+extern int blend2_surf_needed_plb(igd_display_context_t *display,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	unsigned int         flags,
+	igd_surface_t       *blend_surf,
+	igd_rect_t          *blend_rect);
+extern int alter_ovl2_plb(igd_display_context_t *display,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	igd_ovl_info_t      *ovl_info,
+	unsigned int         flags);
+extern int query_ovl2_plb(igd_display_h display_h,
+	unsigned int flags);
+extern int query_max_size_ovl2_plb(igd_display_h display_h,
+	unsigned long pf,
+	unsigned int *max_width,
+	unsigned int *max_height);
+#endif /* _OVL2_NAP_H */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_regs_plb.h b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_regs_plb.h
new file mode 100644
index 0000000..6460560
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl2_regs_plb.h
@@ -0,0 +1,76 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl2_regs_plb.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the internal header file for napa overlay engine. It should be not be
+ *  by any other module besides the overlay module itself. It contains the
+ *  neccessary hardware virtualized structures and functions internal to
+ *  the napa core's overlay engine
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _OVL2_REGS_PLB_H
+#define _OVL2_REGS_PLB_H
+/* Second Overlay Structure.
+ * These registers are the trigger registers and should be written
+ * last. */
+typedef struct _ovl2_reg_plb{
+	unsigned int control;
+	unsigned int start;
+} ovl2_reg_plb_t;
+
+/* Color Correction */
+#define OVL2_RGB_COLOR_DEF_CONT_BRGHT    0x1000000
+#define OVL2_RGB_COLOR_DEF_SATN_HUE      0x0000080
+
+/* Overlay Command Definitions */
+/* 422 Swap */
+#define OVL2_CMD_YVYU				0x00020000
+#define OVL2_CMD_UYVY				0x00010000
+#define OVL2_CMD_VYUY				0x00030000
+
+/* Source Format */
+#define OVL2_CMD_ARGB_8888          0x1C000000
+#define OVL2_CMD_RGB_8888			0x18000000
+#define OVL2_CMD_RGB_565			0x14000000
+#define OVL2_CMD_RGB_555			0x10000000
+#define OVL2_CMD_RGB_8				0x08000000
+#define OVL2_CMD_YUV_422			0x00000000 /*packed YUV422*/
+#define OVL2_CMD_SRC_FMT_MASK		0x3C000000 /*mask for above*/
+
+#define OVL2_REG_ADDR_GAMMA5						0x721E0
+#define OVL2_REG_ADDR_GAMMA4						0x721E4
+#define OVL2_REG_ADDR_GAMMA3						0x721E8
+#define OVL2_REG_ADDR_GAMMA2						0x721EC
+#define OVL2_REG_ADDR_GAMMA1						0x721F0
+#define OVL2_REG_ADDR_GAMMA0						0x721F4
+#define OVL2_TOTAL_GAMMA_REG						6
+
+/* following value are needed because hardware seems to display yuv slightly dimmer
+   than RGB when color data is calculated out to be equal */
+#define MID_CONTRAST_YUV					0x43//4a
+#define MID_SATURATION_YUV					0x91//92
+#define MID_BRIGHTNESS_YUV					-5
+#endif /* _OVL2_REGS_NAP_H */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb.c b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb.c
new file mode 100644
index 0000000..42d4a01
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb.c
@@ -0,0 +1,2188 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_plb.c
+ * $Revision: 1.30 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains function that actually programs the overlay
+ *  register back buffer with the bits to properly configure
+  *  the overlay
+ *  Also includes functions to execute the overlay flip instruction,
+ *  and query the overlay flip status.
+ *  Also contains some hardware capabilities querrying functions
+ *  for upper overlay layer to get this chips overlay capabilities
+ *-----------------------------------------------------------------------------
+ */
+
+#define MODULE_NAME hal.overlay
+
+#include <math_fix.h>
+#include <plb/cmd.h>
+#include "ovl_plb_cache.h"
+#include "../cmn/ovl_dispatch.h"
+#include "../cmn/ovl_virt.h"
+#include "../cmn/ovl_coeff.h"
+#include "ovl2_plb.h"
+
+/*-----------------------------------------------------------------------------
+ * Common dispatch functions
+ *---------------------------------------------------------------------------*/
+static int alter_ovl_plb(igd_display_context_t *display,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	igd_ovl_info_t      *ovl_info,
+	unsigned int         flags);
+static int query_ovl_plb(igd_display_h display_h,
+	unsigned int flags);
+static int query_max_size_ovl_plb(igd_display_h display_h,
+	unsigned long pf,
+	unsigned int *max_width,
+	unsigned int *max_height);
+
+
+ovl_dispatch_t ovl_dispatch_plb[] = {
+	/* Dispatch for the hardware overlay */
+	{
+		NULL, /*blend_surf_needed_plb,*/
+		alter_ovl_plb,
+		query_ovl_plb,
+		query_max_size_ovl_plb,
+	},
+	/* Dispatch for the software overlay */
+	{
+		NULL, /*blend2_surf_needed_plb,*/
+		alter_ovl2_plb,
+		query_ovl2_plb,
+		query_max_size_ovl2_plb,
+	},
+};
+
+
+typedef struct _ovl_chipset_plb {
+	unsigned int	num_linebuf;
+	unsigned int	pixel_format;
+	unsigned int	max_width;
+	unsigned int	max_height;
+} ovl_chipset_plb_t;
+
+static ovl_chipset_plb_t ovl_chipset_plb[] = {
+	{OVL_CONFIG_THREE_LINE_BUFF,
+		(PF_DEPTH_16 | PF_TYPE_YUV_PACKED), 1280, 1080},
+	{OVL_CONFIG_THREE_LINE_BUFF,
+		(PF_DEPTH_8 | PF_TYPE_YUV_PLANAR), 1024, 1080},
+	{OVL_CONFIG_THREE_LINE_BUFF,
+		(PF_DEPTH_32 | PF_TYPE_ARGB), 640, 1080},
+	{OVL_CONFIG_THREE_LINE_BUFF,
+		(PF_DEPTH_32 | PF_TYPE_RGB), 640, 1080},
+
+	{OVL_CONFIG_TWO_LINE_BUFF,
+		(PF_DEPTH_16 | PF_TYPE_YUV_PACKED), 1920, 1088},
+	{OVL_CONFIG_TWO_LINE_BUFF,
+		(PF_DEPTH_8 | PF_TYPE_YUV_PLANAR), 1920, 1088},
+	{OVL_CONFIG_TWO_LINE_BUFF,
+		(PF_DEPTH_32 | PF_TYPE_ARGB), 960, 1080},
+	{OVL_CONFIG_TWO_LINE_BUFF,
+		(PF_DEPTH_32 | PF_TYPE_RGB), 960, 1080},
+	{OVL_CONFIG_NO_LINE_BUFF, 0, 0, 0}
+};
+
+#ifdef DEBUG_BUILD_TYPE
+
+static void ovl_dump_regs_plb(
+	ovl_reg_image_plb_t *ovl_regs_plb)
+{
+	return;
+
+	printk (KERN_ERR "************************************************\n");
+	printk (KERN_ERR "OVERLAY REGISTER LISTING\n");
+
+	printk (KERN_ERR "OVL REGS AT  =    0x%x  \n", (unsigned int)ovl_regs_plb);
+	if(ovl_regs_plb->buffer0_yrgb_ptr)
+		printk (KERN_ERR "RGB POINTER 0    =     0x%x  \n",
+			ovl_regs_plb->buffer0_yrgb_ptr);
+	if(ovl_regs_plb->buffer1_yrgb_ptr)
+		printk (KERN_ERR "RGB POINTER 1    =     0x%x  \n",
+			ovl_regs_plb->buffer1_yrgb_ptr);
+	if(ovl_regs_plb->buffer0_u_ptr)
+		printk (KERN_ERR "U POINTER 0      =     0x%x  \n",
+			ovl_regs_plb->buffer0_u_ptr);
+	if(ovl_regs_plb->buffer0_v_ptr)
+		printk (KERN_ERR "V POINTER 0      =     0x%x  \n",
+			ovl_regs_plb->buffer0_v_ptr);
+	if(ovl_regs_plb->buffer1_u_ptr)
+		printk (KERN_ERR "U POINTER 1      =     0x%x  \n",
+			ovl_regs_plb->buffer1_u_ptr);
+	if(ovl_regs_plb->buffer1_v_ptr)
+		printk (KERN_ERR "V POINTER 1      =     0x%x  \n",
+			ovl_regs_plb->buffer1_v_ptr);
+
+	printk (KERN_ERR "RGB STRIDE       =     0x%x  \n",
+		ovl_regs_plb->yrgb_stride);
+	printk (KERN_ERR "UV STRIDE        =     0x%x  \n",
+		ovl_regs_plb->uv_stride);
+	printk (KERN_ERR "DST POS X        =     %d  \n",
+		ovl_regs_plb->dest_pos_x_left);
+	printk (KERN_ERR "DST POS Y        =     %d  \n",
+		ovl_regs_plb->dest_pos_y_top);
+	printk (KERN_ERR "DST WIDTH        =     %d  \n",
+		ovl_regs_plb->dest_width_x);
+	printk (KERN_ERR "DST HEIGHT       =     %d  \n",
+		ovl_regs_plb->dest_height_y);
+	printk (KERN_ERR "SRC WIDTH        =     %d  \n",
+		ovl_regs_plb->source_yrgb_width);
+	printk (KERN_ERR "SRC SWWIDTH      =     0x%x  \n",
+		ovl_regs_plb->source_yrgb_width_swords);
+	printk (KERN_ERR "SRC HEIGHT       =     %d  \n",
+		ovl_regs_plb->source_yrgb_height);
+	printk (KERN_ERR "UV SRC WIDTH     =     %d  \n",
+		ovl_regs_plb->source_uv_width);
+	printk (KERN_ERR "UV SRC SWWIDTH   =     %d  \n",
+		ovl_regs_plb->source_uv_width_swords);
+	printk (KERN_ERR "UV SRC HEIGHT    =     %d  \n",
+		ovl_regs_plb->source_uv_height);
+	printk (KERN_ERR "RGB SCALE        =     0x%x  \n",
+		ovl_regs_plb->yrgb_scale);
+	printk (KERN_ERR "UV SCALE         =     0x%x  \n",
+		ovl_regs_plb->uv_scale);
+	printk (KERN_ERR "COL CTL BRT CON  =     0x%x  \n",
+		ovl_regs_plb->col_ctl_brt_con);
+	printk (KERN_ERR "COL CTL SAT HUE  =     0x%x  \n",
+		ovl_regs_plb->col_ctl_sat_hue);
+	printk (KERN_ERR "DST COLOR KEY    =     0x%x  \n",
+		ovl_regs_plb->dest_ckey_val);
+	printk (KERN_ERR "DST COLOR KEY MASK =   0x%x  \n",
+		ovl_regs_plb->dest_ckey_mask);
+	printk (KERN_ERR "SRC COLOR KEY HI =     0x%x  \n",
+		ovl_regs_plb->source_ckey_high);
+	printk (KERN_ERR "SRC COLOR KEY LO =     0x%x  \n",
+		ovl_regs_plb->source_ckey_low);
+	printk (KERN_ERR "SRC COLOR KEY MASK =   0x%x  \n",
+		ovl_regs_plb->source_ckey_mask);
+	printk (KERN_ERR "OVL CONFIG       =     0x%x  \n", ovl_regs_plb->config);
+	printk (KERN_ERR "OVL CMD          =     0x%x  \n", ovl_regs_plb->command);
+	printk (KERN_ERR "FAST_V_DSCALE    =     0x%x  \n",
+		ovl_regs_plb->vert_downscale);
+	printk (KERN_ERR "************************************************\n");
+}
+#endif
+
+/*----------------------------------------------------------------------
+ * Function: ovl_check_pf_plb()
+ * Parameters: unsigned int requested_pixel_format -
+ *             according to definitions in igd_mode.h
+ *
+ * Description:
+ *
+ * Returns:
+ *   TRUE on Success
+ *   FALSE on The first pixel format that is supported
+ *----------------------------------------------------------------------*/
+static unsigned int ovl_check_pf_plb(
+	igd_display_context_t *display,
+	unsigned int requested_pixel_format)
+{
+	unsigned long *overlay_pfs;
+	int temp_loop = 0;
+
+	display->context->dispatch.get_pixelformats(
+		(igd_display_h)display, NULL, NULL, &overlay_pfs, NULL, NULL);
+
+	while(overlay_pfs[temp_loop]) {
+		if(overlay_pfs[temp_loop] == requested_pixel_format) {
+			return TRUE;
+		}
+		++temp_loop;
+	}
+
+	return FALSE;
+}
+
+static unsigned int get_uv_shift_x (unsigned long pf)
+{
+
+	switch(pf) {
+	case IGD_PF_YUV422_PACKED_YUY2:
+	case IGD_PF_YUV422_PACKED_UYVY:
+	case IGD_PF_YUV420_PLANAR_I420: /* same as IYUV */
+	case IGD_PF_YUV420_PLANAR_YV12:
+	case IGD_PF_YUV420_PLANAR_NV12:
+		return 1;
+		break;
+	case IGD_PF_YUV410_PLANAR_YVU9:
+		return 2;
+		break;
+	default:
+		return 0;
+	}
+
+}
+
+static unsigned int get_uv_shift_y (unsigned long pf)
+{
+
+	switch(pf) {
+	case IGD_PF_YUV420_PLANAR_I420: /* same as IYUV */
+	case IGD_PF_YUV420_PLANAR_YV12:
+	case IGD_PF_YUV420_PLANAR_NV12:
+		return 1;
+		break;
+	case IGD_PF_YUV410_PLANAR_YVU9:
+		return 2;
+		break;
+	default:
+		return 0;
+	}
+
+}
+
+static unsigned int ovl_check_plb(igd_display_context_t *display,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	igd_ovl_info_t      *ovl_info,
+	unsigned int         flags)
+{
+	igd_timing_info_t *timing;
+	ovl_chipset_plb_t *ovl_chip;
+	unsigned int min_w, min_h;
+
+	EMGD_TRACE_ENTER;
+
+	if (!display){
+		EMGD_ERROR_EXIT("display is null");
+		return -IGD_ERROR_INVAL;
+	}
+	if (!PIPE(display)){
+		EMGD_ERROR_EXIT("PIPE(display) is null");
+		return -IGD_ERROR_INVAL;
+	}
+
+	timing = PIPE(display)->timing;
+
+	/* DCT-PC99TA crashes with dotclock > 300MHz */
+	if(timing->dclk >= 340000){
+		EMGD_ERROR_EXIT("Cannot support dotclock > 340MHz for this SKU");
+		return -IGD_ERROR_HWERROR;
+	}
+
+	/* The following parameters are only valid if the overlay is on, so
+	 * return success if the overlay is being turned off. */
+	if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+		EMGD_TRACE_EXIT;
+		return IGD_SUCCESS;
+	}
+
+	/*************************************************************************
+	 * Ensure the overlay surface is ok and can be properly displayed.
+	 * This ensures the following is valid:
+	 *    - Ensure x1, x2, y1, y2 are pixel aligned
+	 *    - 2 pixels or greater in width and height
+	 *    - Pixel format is supported by the overlay
+	 *    - Pitch is <= 8KB
+	 *    - Based on the pixel format, the width is supported
+	 *************************************************************************/
+	if (!src_surf){
+		EMGD_ERROR_EXIT("src_surf is null");
+		return -IGD_ERROR_INVAL;
+	}
+	if (!src_rect){
+		EMGD_ERROR_EXIT("src_rect is null");
+		return -IGD_ERROR_INVAL;
+	}
+
+	/* Get the minimum size of 1 pixel in width and height for y, u, and v.
+	 */
+	min_w = 1 << get_uv_shift_x(src_surf->pixel_format);
+	min_h = 1 << get_uv_shift_y(src_surf->pixel_format);
+
+	if (((src_rect->x2 - src_rect->x1) < min_w*2) ||
+		((src_rect->y2 - src_rect->y1) < min_h*2)) {
+		EMGD_ERROR_EXIT(
+			"Overlay source width or height is < 2 pixels (%dx%d)\n",
+			src_rect->x2 - src_rect->x1, src_rect->y2 - src_rect->y1);
+		return -IGD_ERROR_INVAL;
+	}
+
+	if (FALSE == ovl_check_pf_plb(display, src_surf->pixel_format)) {
+		EMGD_ERROR_EXIT("Overlay source pixel format unsupported (pf:0x%lx)",
+			src_surf->pixel_format);
+		return -IGD_ERROR_HWERROR;
+	}
+
+	if (src_surf->pitch > 8192) {
+		EMGD_ERROR_EXIT("Overlay source pitch (%d) > 8KB",
+			src_surf->pitch);
+		return -IGD_ERROR_HWERROR;
+	}
+
+	ovl_chip = ovl_chipset_plb;
+	while(ovl_chip->num_linebuf != OVL_CONFIG_NO_LINE_BUFF){
+		if(((src_surf->pixel_format & IGD_PF_MASK) ==
+				ovl_chip->pixel_format) &&
+			(src_surf->width <= ovl_chip->max_width)) {
+			break;
+		}
+		ovl_chip++;
+	}
+	if (ovl_chip->num_linebuf == OVL_CONFIG_NO_LINE_BUFF) {
+		EMGD_ERROR_EXIT("Overlay source width (%d) > max supported",
+			src_surf->width);
+		return -IGD_ERROR_HWERROR;
+	}
+
+	/*************************************************************************
+	 * Ensure the location on the framebuffer is ok and can be properly
+	 * displayed
+	 * This ensures the following is valid:
+	 *    - Greater than 1 pixel width and height
+	 *    - Will be displayed on screen (not panned off)
+	 *************************************************************************/
+	if (!dest_rect){
+		EMGD_ERROR_EXIT("dest_rect is null");
+		return -IGD_ERROR_INVAL;
+	}
+	if (((dest_rect->x2 - dest_rect->x1) <= 1) ||
+		((dest_rect->y2 - dest_rect->y1) <= 1)) {
+		EMGD_ERROR_EXIT(
+			"Overlay dest width or height is single pixel (%dx%d)\n",
+			dest_rect->x2 - dest_rect->x1, dest_rect->y2 - dest_rect->y1);
+		return -IGD_ERROR_INVAL;
+	}
+
+	if ((dest_rect->x1 >= timing->width) ||
+		(dest_rect->y1 >= timing->height)) {
+		EMGD_ERROR_EXIT(
+			"Overlay dest is panned off the screen (%d,%d)\n",
+			dest_rect->x1, dest_rect->y1);
+		return -IGD_ERROR_INVAL;
+	}
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+
+
+static unsigned int ovl_update_src_plb(igd_display_context_t *display,
+	ovl_reg_image_plb_t *ovl_regs_plb,
+	igd_surface_t *src_surf,
+	igd_rect_t    *src_rect)
+{
+	ovl_chipset_plb_t *ovl_chip;
+	unsigned int      src_Bpp;
+	unsigned int      src_uv_shift_x, src_uv_shift_y;
+	unsigned short    src_w;
+	unsigned short    src_h;
+
+	EMGD_TRACE_ENTER;
+
+	/* This is in Bytes per pixel */
+	src_Bpp = IGD_PF_BPP(src_surf->pixel_format)/8;
+
+	src_uv_shift_x = get_uv_shift_x(src_surf->pixel_format);
+	src_uv_shift_y = get_uv_shift_y(src_surf->pixel_format);
+
+	src_w = src_rect->x2 - src_rect->x1;
+	src_h = src_rect->y2 - src_rect->y1;
+
+	ovl_regs_plb->yrgb_stride      = (unsigned short)src_surf->pitch;
+	ovl_regs_plb->uv_stride        = (unsigned short)src_surf->u_pitch;
+
+	/* src width */
+	ovl_regs_plb->source_yrgb_width      = src_w;
+	ovl_regs_plb->source_uv_width        = src_w >> src_uv_shift_x;
+
+	/* src width swords - This equation follows the B-Spec */
+	ovl_regs_plb->source_yrgb_width_swords =
+		((((((ovl_regs_plb->buffer0_yrgb_ptr +
+		      (ovl_regs_plb->source_yrgb_width * src_Bpp) +
+		      0x3F) >> 6) -
+		    (ovl_regs_plb->buffer0_yrgb_ptr >> 6)) << 1) - 1) << 2);
+	ovl_regs_plb->source_uv_width_swords   =
+		((((((ovl_regs_plb->buffer0_u_ptr +
+		      (ovl_regs_plb->source_uv_width * src_Bpp) +
+		      0x3F) >> 6) -
+		    (ovl_regs_plb->buffer0_u_ptr >> 6)) << 1) - 1) << 2 );
+
+
+	/* src height */
+	ovl_regs_plb->source_yrgb_height     = src_h;
+	ovl_regs_plb->source_uv_height       = src_h >> src_uv_shift_y;
+
+	/* src pixel format */
+	switch(src_surf->pixel_format){
+	case IGD_PF_YUV422_PACKED_YUY2:
+		ovl_regs_plb->command |= OVL_CMD_YUV_422;
+		break;
+	case IGD_PF_YUV422_PACKED_UYVY:
+		ovl_regs_plb->command |= OVL_CMD_YUV_422 | OVL_CMD_Y_SWAP;
+		break;
+	case IGD_PF_YUV420_PLANAR_I420: /* same as IYUV */
+		ovl_regs_plb->command |= OVL_CMD_YUV_420P;
+		break;
+	case IGD_PF_YUV420_PLANAR_YV12:
+		ovl_regs_plb->command |= OVL_CMD_YUV_420P | OVL_CMD_UV_SWAP;
+		break;
+	case IGD_PF_YUV420_PLANAR_NV12:
+		ovl_regs_plb->command |= OVL_CMD_YUV_NV12;
+		break;
+	case IGD_PF_YUV410_PLANAR_YVU9:
+		ovl_regs_plb->command |= OVL_CMD_YUV_410P;
+		break;
+	case IGD_PF_ARGB32_8888:
+	case IGD_PF_xRGB32_8888:
+		ovl_regs_plb->command |= OVL_CMD_RGB_8888;
+		break;
+	case IGD_PF_RGB16_565:
+		ovl_regs_plb->command |= OVL_CMD_RGB_565;
+		break;
+	case IGD_PF_xRGB16_555:
+	case IGD_PF_ARGB16_1555:
+		ovl_regs_plb->command |= OVL_CMD_RGB_555;
+		break;
+	default:
+		EMGD_ERROR_EXIT("Invalid pixel format: 0x%lx", src_surf->pixel_format);
+		return -IGD_ERROR_HWERROR;
+	}
+
+	/* Turn off YUV to RGB conversion if the src is RGB */
+	if (!(src_surf->pixel_format & PF_TYPE_YUV)) {
+		ovl_regs_plb->config |= (1<<4);
+	}
+
+	ovl_chip = ovl_chipset_plb;
+	ovl_regs_plb->config &= ~OVL_CONFIG_LINE_BUFF_MASK;
+	while(ovl_chip->num_linebuf != OVL_CONFIG_NO_LINE_BUFF){
+		if(((src_surf->pixel_format & IGD_PF_MASK) ==
+				ovl_chip->pixel_format) &&
+			(src_w <= ovl_chip->max_width)) {
+			ovl_regs_plb->config |= ovl_chip->num_linebuf;
+			break;
+		}
+		ovl_chip++;
+	}
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+
+static unsigned int ovl_update_src_ptr_plb(igd_display_context_t *display,
+	ovl_reg_image_plb_t *ovl_regs_plb,
+        igd_surface_t *src_surf,
+	igd_rect_t    *src_rect)
+{
+	unsigned int      src_Bpp;
+	unsigned int      src_uv_shift_x, src_uv_shift_y;
+
+	EMGD_TRACE_ENTER;
+
+	/* This is in Bytes per pixel */
+	src_Bpp = IGD_PF_BPP(src_surf->pixel_format)/8;
+	src_uv_shift_x = get_uv_shift_x(src_surf->pixel_format);
+	src_uv_shift_y = get_uv_shift_y(src_surf->pixel_format);
+
+	/* src surface */
+	ovl_regs_plb->buffer0_yrgb_ptr     =
+		ovl_regs_plb->buffer1_yrgb_ptr =
+		src_surf->offset +
+		(src_rect->y1 * src_surf->pitch) + (src_rect->x1 * src_Bpp);
+
+	/*
+	 * The NV12 format has the UV pixels interleaved so the total
+	 * width of the UV portion of the surface is the same as the
+	 * Y width. Thus, don't do any shifting of the UV plane in the
+	 * X direction.
+	 */
+	if (src_surf->pixel_format == IGD_PF_YUV420_PLANAR_NV12) {
+		ovl_regs_plb->buffer0_u_ptr     =
+			ovl_regs_plb->buffer1_u_ptr =
+			src_surf->u_offset +
+			((src_rect->y1>>src_uv_shift_y) * src_surf->u_pitch) +
+			src_rect->x1;
+
+		ovl_regs_plb->buffer0_v_ptr     =
+			ovl_regs_plb->buffer1_v_ptr =
+			src_surf->v_offset +
+			((src_rect->y1>>src_uv_shift_y) * src_surf->v_pitch) +
+			src_rect->x1;
+	} else {
+		ovl_regs_plb->buffer0_u_ptr     =
+			ovl_regs_plb->buffer1_u_ptr =
+			src_surf->u_offset +
+			((src_rect->y1>>src_uv_shift_y) * src_surf->u_pitch) +
+			(src_rect->x1>>src_uv_shift_x);
+
+		ovl_regs_plb->buffer0_v_ptr     =
+			ovl_regs_plb->buffer1_v_ptr =
+			src_surf->v_offset +
+			((src_rect->y1>>src_uv_shift_y) * src_surf->v_pitch) +
+			(src_rect->x1>>src_uv_shift_x);
+	}
+
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+
+static unsigned int ovl_update_phase_plb(
+	ovl_reg_image_plb_t *ovl_regs_plb,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect)
+{
+
+	EMGD_TRACE_ENTER;
+
+	/*
+	 * Set the Vertical/Horizontal Phase Registers.  Both Field0
+	 * and Field1 are set, although Field1 is only used when
+	 * interleaved.
+	 */
+	switch (src_surf->pixel_format) {
+	case IGD_PF_YUV422_PACKED_YUY2:
+	case IGD_PF_YUV422_PACKED_UYVY:
+		/* YUV 422 */
+		ovl_regs_plb->init_phase_shift = 0;
+
+		/* Vertical Phase */
+		if (ovl_regs_plb->config & OVL_CONFIG_THREE_LINE_BUFF) {
+			ovl_regs_plb->yrgb_vert_phase_field0 = 0;
+			ovl_regs_plb->yrgb_vert_phase_field1 = 0;
+			ovl_regs_plb->uv_vert_phase_field0 = 0;
+			ovl_regs_plb->uv_vert_phase_field1 = 0;
+		} else {
+			ovl_regs_plb->yrgb_vert_phase_field0 = 0x8000; /*.5*/
+			ovl_regs_plb->yrgb_vert_phase_field1 = 0x8000; /*.5*/
+			ovl_regs_plb->uv_vert_phase_field0   = 0x8000; /*.5*/
+			ovl_regs_plb->uv_vert_phase_field1   = 0x8000; /*.5*/
+		}
+
+		/* Horizontal Phase */
+		if (!(src_rect->x1 & 1)) {
+			ovl_regs_plb->yrgb_hphase = 0;
+			ovl_regs_plb->uv_hphase = 0;
+		} else {
+			ovl_regs_plb->init_phase_shift |= Y_HPP_PLUS1;
+			ovl_regs_plb->yrgb_hphase = 0; /*1*/
+			ovl_regs_plb->uv_hphase = 0x8000; /*.5*/
+		}
+		break;
+
+	case IGD_PF_YUV420_PLANAR_I420:
+	case IGD_PF_YUV420_PLANAR_YV12:
+	case IGD_PF_YUV420_PLANAR_NV12:
+		/* YUV 420 */
+		ovl_regs_plb->init_phase_shift = 0;
+
+		/* Vertical Phase */
+		if (ovl_regs_plb->config & OVL_CONFIG_THREE_LINE_BUFF) {
+			if (!(src_rect->y1 & 1)) {
+				ovl_regs_plb->yrgb_vert_phase_field0 = 0; /*0*/
+				ovl_regs_plb->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+				ovl_regs_plb->yrgb_vert_phase_field1 = 0;/*1*/
+
+				ovl_regs_plb->init_phase_shift |= UV_VPP_FLD0_MINUS1;
+				ovl_regs_plb->uv_vert_phase_field0 = 0xc000; /*-.25*/
+				ovl_regs_plb->uv_vert_phase_field1 = 0x4000; /*.25*/
+			} else {
+				ovl_regs_plb->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+				ovl_regs_plb->yrgb_vert_phase_field0 = 0; /*1*/
+				ovl_regs_plb->yrgb_vert_phase_field1 = 0;/*0*/
+
+				ovl_regs_plb->uv_vert_phase_field0 = 0x4000; /*.25*/
+				ovl_regs_plb->init_phase_shift |= UV_VPP_FLD1_MINUS1;
+				ovl_regs_plb->uv_vert_phase_field1 = 0xc000; /*-.25*/
+			}
+		} else {
+			if (!(src_rect->y1 & 1)) {
+				ovl_regs_plb->yrgb_vert_phase_field0 = 0x8000; /*.5*/
+				ovl_regs_plb->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+				ovl_regs_plb->yrgb_vert_phase_field1 = 0x8000;/*1.5*/
+
+				ovl_regs_plb->uv_vert_phase_field0 = 0x4000; /*.25*/
+				ovl_regs_plb->uv_vert_phase_field1 = 0xc000; /*.75*/
+			} else {
+				ovl_regs_plb->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+				ovl_regs_plb->yrgb_vert_phase_field0 = 0x8000;/*1.5*/
+				ovl_regs_plb->yrgb_vert_phase_field1 = 0x8000; /*.5*/
+
+				ovl_regs_plb->uv_vert_phase_field0 = 0xc000; /*.75*/
+				ovl_regs_plb->uv_vert_phase_field1 = 0x4000; /*.25*/
+			}
+		}
+
+		/* Horizontal Phase */
+		if (!(src_rect->x1 & 1)) {
+			ovl_regs_plb->yrgb_hphase = 0;
+			ovl_regs_plb->uv_hphase = 0;
+		} else {
+			ovl_regs_plb->init_phase_shift |= Y_HPP_PLUS1;
+			ovl_regs_plb->yrgb_hphase = 0; /*1*/
+			ovl_regs_plb->uv_hphase = 0x8000; /*.5*/
+		}
+		break;
+
+	case IGD_PF_YUV410_PLANAR_YVU9:
+		/* YUV 410 */
+		ovl_regs_plb->init_phase_shift = 0;
+
+		/* Vertical Phase */
+		if (ovl_regs_plb->config & OVL_CONFIG_THREE_LINE_BUFF) {
+			switch (src_rect->y1 & 3) {
+			default:
+			case 0:
+				ovl_regs_plb->yrgb_vert_phase_field0 = 0; /*0*/
+				ovl_regs_plb->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+				ovl_regs_plb->yrgb_vert_phase_field1 = 0;/*1*/
+
+				ovl_regs_plb->init_phase_shift |= UV_VPP_FLD0_MINUS1;
+				ovl_regs_plb->uv_vert_phase_field0 = 0xa000; /*-.375*/
+				ovl_regs_plb->init_phase_shift |= UV_VPP_FLD1_MINUS1;
+				ovl_regs_plb->uv_vert_phase_field1 = 0xe000; /*-.125*/
+				break;
+
+			case 1:
+				ovl_regs_plb->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+				ovl_regs_plb->yrgb_vert_phase_field0 = 0; /*1*/
+				ovl_regs_plb->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+				ovl_regs_plb->yrgb_vert_phase_field1 = 0;/*1*/
+
+				ovl_regs_plb->init_phase_shift |= UV_VPP_FLD0_MINUS1;
+				ovl_regs_plb->uv_vert_phase_field0 = 0xe000; /*-.125*/
+				ovl_regs_plb->uv_vert_phase_field1 = 0x2000; /*.125*/
+				break;
+
+			case 2:
+				ovl_regs_plb->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+				ovl_regs_plb->yrgb_vert_phase_field0 = 0; /*1*/
+				ovl_regs_plb->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+				ovl_regs_plb->yrgb_vert_phase_field1 = 0;/*1*/
+
+				ovl_regs_plb->uv_vert_phase_field0 = 0x2000; /*.125*/
+				ovl_regs_plb->uv_vert_phase_field1 = 0x6000; /*.375*/
+				break;
+
+			case 3:
+				ovl_regs_plb->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+				ovl_regs_plb->yrgb_vert_phase_field0 = 0; /*1*/
+				ovl_regs_plb->yrgb_vert_phase_field1 = 0;/*0*/
+
+				ovl_regs_plb->uv_vert_phase_field0 = 0x6000; /*.375*/
+				ovl_regs_plb->init_phase_shift |= UV_VPP_FLD1_MINUS1;
+				ovl_regs_plb->uv_vert_phase_field1 = 0xa000; /*-.375*/
+				break;
+			}
+		} else {
+			switch (src_rect->y1 & 3) {
+			default:
+			case 0:
+				ovl_regs_plb->yrgb_vert_phase_field0 = 0x8000; /*.5*/
+				ovl_regs_plb->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+				ovl_regs_plb->yrgb_vert_phase_field1 = 0x8000;/*1.5*/
+
+				ovl_regs_plb->init_phase_shift |= UV_VPP_FLD0_MINUS1;
+				ovl_regs_plb->uv_vert_phase_field0 = 0xc000; /*-.25*/
+				ovl_regs_plb->uv_vert_phase_field1 = 0; /*0*/
+				break;
+
+			case 1:
+				ovl_regs_plb->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+				ovl_regs_plb->yrgb_vert_phase_field0 = 0x8000;/*1.5*/
+				ovl_regs_plb->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+				ovl_regs_plb->yrgb_vert_phase_field1 = 0x8000; /*1.5*/
+
+				ovl_regs_plb->uv_vert_phase_field0 = 0x0; /*0*/
+				ovl_regs_plb->uv_vert_phase_field1 = 0x4000; /*.25*/
+				break;
+
+			case 2:
+				ovl_regs_plb->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+				ovl_regs_plb->yrgb_vert_phase_field0 = 0x8000;/*1.5*/
+				ovl_regs_plb->init_phase_shift |= Y_VPP_FLD1_PLUS1;
+				ovl_regs_plb->yrgb_vert_phase_field1 = 0x8000; /*1.5*/
+
+				ovl_regs_plb->uv_vert_phase_field0 = 0x4000; /*.25*/
+				ovl_regs_plb->uv_vert_phase_field1 = 0x8000; /*.5*/
+				break;
+
+			case 3:
+				ovl_regs_plb->init_phase_shift |= Y_VPP_FLD0_PLUS1;
+				ovl_regs_plb->yrgb_vert_phase_field0 = 0x8000;/*1.5*/
+				ovl_regs_plb->yrgb_vert_phase_field1 = 0x8000; /*.5*/
+
+				ovl_regs_plb->uv_vert_phase_field0 = 0x8000; /*.5*/
+				ovl_regs_plb->init_phase_shift |= UV_VPP_FLD1_MINUS1;
+				ovl_regs_plb->uv_vert_phase_field1 = 0xc000; /*-.25*/
+				break;
+			}
+		}
+
+		/* Horizontal Phase */
+		switch (src_rect->x1 & 3) {
+		default:
+		case 0:
+			ovl_regs_plb->yrgb_hphase = 0;
+			ovl_regs_plb->init_phase_shift |= UV_HPP_MINUS1;
+			ovl_regs_plb->uv_hphase = 0xa000; /*-.375*/
+			break;
+
+		case 1:
+			ovl_regs_plb->init_phase_shift |= Y_HPP_PLUS1;
+			ovl_regs_plb->yrgb_hphase = 0; /*1*/
+			ovl_regs_plb->init_phase_shift |= UV_HPP_MINUS1;
+			ovl_regs_plb->uv_hphase = 0xe000; /*-.125*/
+			break;
+
+		case 2:
+			ovl_regs_plb->init_phase_shift |= Y_HPP_PLUS2;
+			ovl_regs_plb->yrgb_hphase = 0; /*2*/
+			ovl_regs_plb->uv_hphase = 0x2000; /*.125*/
+			break;
+
+		case 3:
+			ovl_regs_plb->init_phase_shift |= Y_HPP_PLUS2;
+			ovl_regs_plb->yrgb_hphase = 0xffff; /*3*/
+			ovl_regs_plb->uv_hphase = 0x6000; /*.375*/
+			break;
+		}
+		break;
+
+	default:
+		/* RGB format */
+		ovl_regs_plb->init_phase_shift = 0;
+
+		/* Vertical Phase */
+		if (ovl_regs_plb->config & OVL_CONFIG_THREE_LINE_BUFF) {
+			ovl_regs_plb->yrgb_vert_phase_field0 = 0;
+			ovl_regs_plb->yrgb_vert_phase_field1 = 0;
+			ovl_regs_plb->uv_vert_phase_field0 = 0;
+			ovl_regs_plb->uv_vert_phase_field1 = 0;
+		} else {
+			ovl_regs_plb->yrgb_vert_phase_field0 = 0x8000;
+			ovl_regs_plb->yrgb_vert_phase_field1 = 0x8000;
+			ovl_regs_plb->uv_vert_phase_field0   = 0x8000;
+			ovl_regs_plb->uv_vert_phase_field1   = 0x8000;
+		}
+
+		/* Horizontal Phase */
+		ovl_regs_plb->yrgb_hphase = 0;
+		ovl_regs_plb->uv_hphase = 0;
+		break;
+	}
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+
+
+/*----------------------------------------------------------------------
+ * Function: ovl_update_scale_plb()
+ *
+ * Description: Will update only the scaling registers for the plb core
+ *
+ * Returns:
+ *   N/A
+ *----------------------------------------------------------------------*/
+
+static unsigned int ovl_update_scale_plb(
+	ovl_reg_image_plb_t *ovl_regs_plb,
+	igd_surface_t *src_surf,
+	igd_rect_t   *src_rect,
+	igd_rect_t   *dest_rect,
+	unsigned int flags)
+{
+	unsigned int uv_shift;
+	unsigned int xscale, xscale_int, xscale_fract;
+	unsigned int yscale, yscale_int, yscale_fract;
+	unsigned int xscale_int_uv, xscale_fract_uv;
+	unsigned int yscale_int_uv, yscale_fract_uv;
+
+	EMGD_TRACE_ENTER;
+
+	xscale = ((src_rect->x2 - src_rect->x1)<<12) /
+		(dest_rect->x2 - dest_rect->x1);
+	yscale = ((src_rect->y2 - src_rect->y1)<<12) /
+		(dest_rect->y2 - dest_rect->y1);
+
+	/* In interleaved mode, the y scale is /2 */
+	if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+		yscale >>= 1;
+	}
+
+	xscale_int = (xscale & 0x3000) >> 12;
+	xscale_fract = xscale & 0xfff;
+	yscale_int = (yscale & 0x7ff000) >> 12;
+	yscale_fract = yscale & 0xfff;
+
+	uv_shift = get_uv_shift_x(src_surf->pixel_format);
+	xscale_int_uv = ((xscale>>uv_shift) & 0x3000) >> 12;
+	xscale_fract_uv = (xscale>>uv_shift) & 0xfff;
+
+	uv_shift = get_uv_shift_y(src_surf->pixel_format);
+	yscale_int_uv = ((yscale>>uv_shift) & 0x7ff000) >> 12;
+	yscale_fract_uv = (yscale>>uv_shift) & 0xfff;
+
+	ovl_regs_plb->yrgb_scale =
+		(yscale_fract  << 20) |   /* Vert  Scale Fraction */
+		(xscale_int    << 16) |   /* Horiz Scale Int */
+		(xscale_fract  << 3);     /* Horiz Scale Fraction */
+
+	ovl_regs_plb->uv_scale =
+		(yscale_fract_uv << 20) | /* UV Vert  Scale Fraction */
+		(xscale_int_uv   << 16) | /* UV Horiz Scale Int */
+		(xscale_fract_uv << 3 );  /* UV Horiz Scale Fraction */
+	ovl_regs_plb->vert_downscale =
+		(yscale_int    << 16) |   /* Vert Scale Factor */
+		yscale_int_uv;            /* UV Vert Scale Factor */
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+
+
+/*----------------------------------------------------------------------
+ * Function: ovl_update_video_quality_plb()
+ *
+ * Description:
+ *   This function updates the contrast, brightness, and saturation of
+ *   the overlay using the values specified in overlay_info.
+ *
+ * Returns:
+ *   != 0 on Error
+ *   0 on Success
+ *----------------------------------------------------------------------*/
+
+static int ovl_update_video_quality_plb(
+	ovl_reg_image_plb_t *ovl_regs_plb,
+	igd_surface_t       *src_surf,
+	igd_ovl_video_quality_info_t *video_quality)
+{
+	int                          calc_brightness_tmp = 0;
+	int                          calc_brightness     = 0;
+	unsigned int                 calc_contrast_tmp   = 0;
+	unsigned int                 calc_contrast       = 0;
+	unsigned int                 calc_saturation_tmp = 0;
+	unsigned int                 calc_saturation     = 0;
+
+	EMGD_TRACE_ENTER;
+
+	/* If the src_surf pixel format is RGB, then brightness, contrast,
+	 * and saturation should all be set to the exact default */
+	if (src_surf->pixel_format & PF_TYPE_RGB) {
+		if (video_quality->brightness != 0x8000) {
+			EMGD_DEBUG("RGB surfaces must set brightness to default");
+		}
+		if (video_quality->contrast != 0x8000) {
+			EMGD_DEBUG("RGB surfaces must set contrast to default");
+		}
+		if (video_quality->saturation != 0x8000) {
+			EMGD_DEBUG("RGB surfaces must set saturation to default");
+		}
+
+		ovl_regs_plb->col_ctl_brt_con = OVL_RGB_COLOR_DEF_CONT_BRGHT;
+		ovl_regs_plb->col_ctl_sat_hue = OVL_RGB_COLOR_DEF_SATN_HUE;
+
+		EMGD_TRACE_EXIT;
+		return IGD_SUCCESS;
+	}
+
+	/*************************************************************************
+	 * Brightness
+	 *************************************************************************/
+	if (0x8000 == video_quality->brightness) {
+		calc_brightness = MID_BRIGHTNESS_YUV;
+	} else if (video_quality->brightness < 0x8000) {
+		/*
+		 * we have here a brightness that is less than the default
+		 * mid point
+		 */
+		calc_brightness_tmp = 0x8000 - video_quality->brightness;
+		calc_brightness_tmp <<= 14;
+		calc_brightness_tmp /= 0x8000;
+		calc_brightness     = -128 - MID_BRIGHTNESS_YUV;
+		/*
+		 * more range if the midpoint is positive but less range
+		 * if midpoint is negative
+		 */
+
+		calc_brightness *= calc_brightness_tmp;
+		calc_brightness += BIT13;
+		calc_brightness >>= 14;
+
+		if (calc_brightness < -128) {
+			calc_brightness = -128;
+		}
+		if (calc_brightness > MID_BRIGHTNESS_YUV) {
+			calc_brightness = MID_BRIGHTNESS_YUV;
+		}
+	} else {
+		/*
+		 * we have here a brightness that is more than the default
+		 * mid point
+		 */
+		calc_brightness_tmp = video_quality->brightness - 0x8000;
+		calc_brightness_tmp <<= 14;
+		calc_brightness_tmp /= 0x8000;
+		calc_brightness     = 127 - MID_BRIGHTNESS_YUV;
+		/*
+		 * less range if the midpoint is positive but more range
+		 * if midpoint is negative
+		 */
+		calc_brightness *= calc_brightness_tmp;
+		calc_brightness += BIT13;
+		calc_brightness >>= 14;
+
+		if (calc_brightness > 127) {
+			calc_brightness = 127;
+		}
+		if (calc_brightness < MID_BRIGHTNESS_YUV) {
+			calc_brightness = MID_BRIGHTNESS_YUV;
+		}
+	}
+
+	ovl_regs_plb->col_ctl_brt_con =
+		(ovl_regs_plb->col_ctl_brt_con & 0xFFFFFF00) |
+		(calc_brightness & 0xFF);
+
+	/*************************************************************************
+	 * Contrast
+	 *************************************************************************/
+	if (0x8000 == video_quality->contrast ){
+		calc_contrast = MID_CONTRAST_YUV;
+	} else if (video_quality->contrast < 0x8000) {
+		/* we have here a contrast that is less than the
+		 * default mid point */
+		calc_contrast_tmp = video_quality->contrast;
+		calc_contrast_tmp <<= 12;
+		calc_contrast_tmp /= 0x8000;
+		calc_contrast     = MID_CONTRAST_YUV;
+		calc_contrast     *= calc_contrast_tmp;
+		calc_contrast     += BIT11;
+		calc_contrast     >>= 12;
+		if (calc_contrast > 0x3F) {
+			calc_contrast = 0x3F;
+		}
+	} else {
+		/* we have here a contrast that is more than the
+		 * default mid point */
+		calc_contrast_tmp = video_quality->contrast - 0x8000;
+		calc_contrast_tmp <<= 12;
+		calc_contrast_tmp /= 0x8000;
+		calc_contrast     = (0x1FF - MID_CONTRAST_YUV);
+		calc_contrast     *= calc_contrast_tmp;
+		calc_contrast     += BIT11;
+		calc_contrast     >>= 12;
+		calc_contrast     += MID_CONTRAST_YUV;
+		if (calc_contrast > 0x1FF) {
+			calc_contrast = 0x1FF;
+		}
+	}
+
+	ovl_regs_plb->col_ctl_brt_con =
+		(ovl_regs_plb->col_ctl_brt_con & 0xF803FFFF) |
+		((calc_contrast & 0x1FF) << 18);
+
+	/*************************************************************************
+	 * Saturation
+	 *************************************************************************/
+	if (video_quality->saturation == 0x8000) {
+		calc_saturation = MID_SATURATION_YUV;
+	} else if (video_quality->saturation < 0x8000) {
+		/* we have here a saturation that is less than the default
+		 * mid point */
+		calc_saturation_tmp = video_quality->saturation;
+		calc_saturation_tmp <<= 12;
+		calc_saturation_tmp /= 0x8000;
+		calc_saturation     = MID_SATURATION_YUV;
+		calc_saturation     *= calc_saturation_tmp;
+		calc_saturation     += BIT11;
+		calc_saturation     >>= 12;
+		if (calc_saturation > 0x7F) {
+			calc_saturation = 0x7F;
+		}
+	} else {
+		/* we have here a saturation that is more than the default
+		 * mid point*/
+		calc_saturation_tmp = video_quality->saturation - 0x8000;
+		calc_saturation_tmp <<= 12;
+		calc_saturation_tmp /= 0x8000;
+		calc_saturation     = (0x3FF - MID_SATURATION_YUV);
+		calc_saturation     *= calc_saturation_tmp;
+		calc_saturation     += BIT11;
+		calc_saturation     >>= 12;
+		calc_saturation     += MID_SATURATION_YUV;
+
+		if (calc_saturation > 0x3FF) {
+			calc_saturation = 0x3FF;
+		}
+	}
+
+	ovl_regs_plb->col_ctl_sat_hue =
+		(ovl_regs_plb->col_ctl_sat_hue & 0xFFFFFC00) |
+		(calc_saturation & 0x3FF);
+
+	/*************************************************************************
+	 * Hue
+	 *************************************************************************/
+	/* Hue is always set to the default value.  It is based on the saturation
+	 * value, and having a separate hue is of minimal value. */
+	ovl_regs_plb->col_ctl_sat_hue =
+		(ovl_regs_plb->col_ctl_sat_hue & 0xF800FFFF);
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+
+
+static void check_gamma(unsigned int *gamma)
+{
+
+	if (*gamma < IGD_OVL_GAMMA_MIN) {
+		EMGD_ERROR("Gamma to small (0x%x in 24i.8f format), "
+			"changing to Min Gamma (0.6)",
+			*gamma);
+		*gamma = IGD_OVL_GAMMA_MIN;
+	}
+	if (*gamma > IGD_OVL_GAMMA_MAX) {
+		EMGD_ERROR("Gamma to large (0x%x in 24i.8f format), "
+			"changing to Max Gamma (6.0)",
+			*gamma);
+		*gamma = IGD_OVL_GAMMA_MAX;
+	}
+
+	return;
+}
+
+
+
+/*-----------------------------------------------------------------------------
+ * Function: ovl_update_gamma_plb()
+ *
+ * Description:
+ *    This function sets the gamma correction values for the overlays.
+ *
+ * Returns:
+ *   != 0 on Error
+ *   IGD_SUCCESS on Success
+ *---------------------------------------------------------------------------*/
+static int ovl_update_gamma_plb(
+	igd_display_context_t *display,
+	igd_ovl_gamma_info_t * ovl_gamma)
+{
+	const int gamma_reg_input[OVL_TOTAL_GAMMA_REG] = {8, 16, 32, 64, 128, 192};
+	const int gamma_reg_offset[OVL_TOTAL_GAMMA_REG] = {
+		OVL_REG_ADDR_GAMMA0,
+		OVL_REG_ADDR_GAMMA1,
+		OVL_REG_ADDR_GAMMA2,
+		OVL_REG_ADDR_GAMMA3,
+		OVL_REG_ADDR_GAMMA4,
+		OVL_REG_ADDR_GAMMA5
+	};
+	const unsigned int gamma_def[OVL_TOTAL_GAMMA_REG] = {
+		0x00080808,
+		0x00101010,
+		0x00202020,
+		0x00404040,
+		0x00808080,
+		0x00c0c0c0
+	};
+	unsigned int          new_gamma_red_24i_8f, new_gamma_green_24i_8f;
+	unsigned int          new_gamma_blue_24i_8f;
+	unsigned int          gamma_normal_r_24i_8f;
+	unsigned int          gamma_normal_g_24i_8f;
+	unsigned int          gamma_normal_b_24i_8f;
+	unsigned int          gamma_reg, gamma_reg_24i_8f;
+	unsigned int          i;
+
+	EMGD_TRACE_ENTER;
+
+	/* FIXME: The gamma values are re-written for every alter_ovl call.
+	 * This may cause issues or may be to slow?  If so, store the previous
+	 * values and only re-write when they change. */
+
+	/* If the overlay gamma is disabled, set it to the default */
+	if ((ovl_gamma->flags & IGD_OVL_GAMMA_ENABLE) == IGD_OVL_GAMMA_DISABLE) {
+		for (i = 0; i < OVL_TOTAL_GAMMA_REG; i++) {
+			/* program register */
+			EMGD_WRITE32(gamma_def[i], MMIO(display) + gamma_reg_offset[i]);
+		}
+		EMGD_TRACE_EXIT;
+		return IGD_SUCCESS;
+	}
+
+	/* It is assumed that the input value is a 24-bit number */
+	new_gamma_red_24i_8f   = ovl_gamma->red;
+	new_gamma_green_24i_8f = ovl_gamma->green;
+	new_gamma_blue_24i_8f  = ovl_gamma->blue;
+
+	/* Ensure the gamma values are between MIN and MAX */
+	check_gamma(&new_gamma_red_24i_8f);
+	check_gamma(&new_gamma_green_24i_8f);
+	check_gamma(&new_gamma_blue_24i_8f);
+
+	/*
+	 * Program RGB for each of the 6 gamma registers
+	 */
+
+	/* Since the OS_POW_FIX function can only take an integer base,
+	 * we need to normalize the result by gamma_normal_x
+	 */
+	gamma_normal_r_24i_8f =  OS_POW_FIX(255, (1<<16)/new_gamma_red_24i_8f);
+	gamma_normal_g_24i_8f =  OS_POW_FIX(255, (1<<16)/new_gamma_green_24i_8f);
+	gamma_normal_b_24i_8f =  OS_POW_FIX(255, (1<<16)/new_gamma_blue_24i_8f);
+
+	for( i = 0; i < OVL_TOTAL_GAMMA_REG; i++ )
+	{
+		/* red */
+		gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+								(1<<16)/new_gamma_red_24i_8f);
+		gamma_reg        =
+			((255 * gamma_reg_24i_8f) / gamma_normal_r_24i_8f) << 16;
+
+		/* green */
+		gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+							(1<<16)/new_gamma_green_24i_8f);
+		gamma_reg        |=
+			((255 * gamma_reg_24i_8f) / gamma_normal_g_24i_8f) << 8;
+
+		/* blue */
+		gamma_reg_24i_8f = OS_POW_FIX(gamma_reg_input[i],
+							(1<<16)/new_gamma_blue_24i_8f);
+		gamma_reg        |=
+			((255 * gamma_reg_24i_8f) / gamma_normal_b_24i_8f);
+
+		/* turn overlay off (TBD) */
+
+		/* program register */
+		EMGD_WRITE32(gamma_reg, MMIO(display) + gamma_reg_offset[i]);
+
+		/* turn overlay on (TBD) */
+	}
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+
+
+/*----------------------------------------------------------------------
+ * Function: ovl_update_coeff_plb()
+ * Description: Function to calculate the filter coeffcient
+ *              registers for plb
+ * Notes in Usage:
+ *
+ *----------------------------------------------------------------------*/
+static unsigned int ovl_update_coeff_plb(
+	ovl_reg_image_plb_t *ovl_regs_plb,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	unsigned int        flags)
+{
+	unsigned int scale_int, scale_fpint;
+
+	unsigned int dest_h = dest_rect->y2 - dest_rect->y1;
+	unsigned int dest_w = dest_rect->x2 - dest_rect->x1;
+	unsigned int src_h  = src_rect->y2  - src_rect->y1;
+	unsigned int src_w  = src_rect->x2  - src_rect->x1;
+
+	EMGD_TRACE_ENTER;
+
+	/* FIXME: The coeff values are re-written for every alter_ovl call.
+	 * This may cause issues or may be to slow?  If so, store the previous
+	 * values and only re-write when they change. */
+
+	/* In interleaved mode, the src_h is /2 */
+	if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+		src_h >>= 1;
+	}
+
+	/* Y Horizontal */
+	scale_int = ((ovl_regs_plb->yrgb_scale) >> 16) & 0x7;
+
+	if (!scale_int) {
+		/* upscale - clamp to 1.0 */
+		scale_fpint = 1<<20;
+	} else {
+		scale_fpint = ((src_w << 20) / dest_w) / scale_int;
+	}
+    ovl_update_coeff_regs(5, scale_fpint, 1, 1,
+                          (unsigned short *)ovl_regs_plb->y_horz_coeff_single);
+
+	/* Y Vertical */
+	scale_int = ((ovl_regs_plb->vert_downscale) >> 16) & 0x7ff;
+	if (!scale_int) {
+		/* upscale - clamp to 1.0 */
+		scale_fpint = 1<<20;
+	} else {
+		scale_fpint = ((src_h << 20) / dest_h) / scale_int;
+	}
+	ovl_update_coeff_regs(3, scale_fpint, 0, 1,
+                          (unsigned short *)ovl_regs_plb->y_vert_coeff_single);
+
+	/* UV Horizontal */
+	scale_int = ((ovl_regs_plb->uv_scale) >> 16) & 0x7;
+	if (!scale_int) {
+		/* upscale - clamp to 1.0 */
+		scale_fpint = 1<<20;
+	} else {
+		scale_fpint = ((src_w << 20) / dest_w) / scale_int;
+		scale_fpint >>= get_uv_shift_x(src_surf->pixel_format);
+	}
+	ovl_update_coeff_regs(3, scale_fpint , 1, 0,
+                          (unsigned short *)ovl_regs_plb->uv_horz_coeff_single);
+
+	/* UV Vertical */
+	scale_int = (ovl_regs_plb->vert_downscale) & 0x7ff;
+	if (!scale_int) {
+		/* upscale - clamp to 1.0 */
+		scale_fpint = 1<<20;
+	} else {
+		scale_fpint = ((src_h << 20) / dest_h) / scale_int;
+		scale_fpint >>= get_uv_shift_y(src_surf->pixel_format);
+	}
+	ovl_update_coeff_regs(3, scale_fpint, 0, 0,
+                          (unsigned short *)ovl_regs_plb->uv_vert_coeff_single);
+
+	/* Adjust for 2-line Vertical Buffer */
+	if((ovl_regs_plb->config & OVL_CONFIG_LINE_BUFF_MASK)==
+		OVL_CONFIG_TWO_LINE_BUFF){
+		ovl_update_coeff_regs(2, 0x10, 0, 1,
+			(unsigned short *)ovl_regs_plb->y_vert_coeff_single);
+		ovl_update_coeff_regs(2, 0x10, 0, 0,
+			(unsigned short *)ovl_regs_plb->uv_vert_coeff_single);
+	}
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+static unsigned int convert_color_key_to_hw (
+	unsigned long pf,
+	unsigned int input)
+{
+	unsigned int output;
+
+	switch (pf) {
+	case IGD_PF_ARGB32:
+	case IGD_PF_xRGB32:
+	case IGD_PF_ARGB8_INDEXED:
+	default:
+		output = input;
+		break;
+	case IGD_PF_RGB16_565:
+		output =
+			((((input & 0xf800)>>11)<<3)<<16) |
+			((((input & 0x07e0)>>5 )<<2)<<8 ) |
+			((((input & 0x001f)>>0 )<<3)<<0 );
+		break;
+	case IGD_PF_ARGB16_1555:
+		output =
+			((((input & 0x7c00)>>10)<<3)<<16) |
+			((((input & 0x03e0)>>5 )<<3)<<8 ) |
+			((((input & 0x001f)>>0 )<<3)<<0 );
+		break;
+	}
+
+	return output;
+}
+static unsigned int convert_color_key_to_mask (
+	unsigned long pf,
+	unsigned int input)
+{
+	unsigned int output;
+
+	switch (pf) {
+	case IGD_PF_ARGB32:
+	case IGD_PF_xRGB32:
+	default:
+		output = 0x00000000;
+		break;
+	case IGD_PF_RGB16_565:
+		output = 0x00070307;
+		break;
+	case IGD_PF_ARGB16_1555:
+		output = 0x00070707;
+		break;
+	case IGD_PF_ARGB8_INDEXED:
+		output = 0x00ffff00;
+		break;
+	}
+
+	return output;
+}
+
+/* Convert RGB to GBR for 32bpp and 16bpp pixel formats.
+ * Do not convert YUV surfaces or RGB indexed pixel formats */
+static unsigned int rgb_to_gbr(
+	unsigned long pf,
+	unsigned int input)
+{
+	unsigned int output;
+
+	if (((pf & IGD_PF_TYPE_MASK) == PF_TYPE_ARGB) &&
+		((pf & IGD_PF_DEPTH_MASK) != PF_DEPTH_8)) {
+		output =
+			((input & 0x00ff0000) >> 16) |
+			((input & 0x0000ff00) << 8)  |
+			((input & 0x000000ff) << 8);
+	} else {
+		output = input;
+	}
+
+	return output;
+}
+
+
+#ifndef OVL_PLB_CACHE_QUICK_SWAP  /* If no OVL_PLB_CACHE_QUICK_SWAP */
+
+static unsigned int ovl_update_regs_plb(
+	igd_display_context_t *display,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	igd_ovl_info_t      *ovl_info,
+	unsigned int         flags)
+{
+	ovl_reg_image_plb_t *ovl_regs_plb, *ovl_cache_plb ;
+	int ret;
+
+	EMGD_TRACE_ENTER;
+
+	ovl_regs_plb = phys_to_virt(ovl_context->reg_update_phys);
+	ovl_cache_plb = OS_ALLOC(sizeof(ovl_reg_image_plb_t));
+	OS_MEMSET(ovl_cache_plb, 0, sizeof(ovl_reg_image_plb_t));
+
+	if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+		/* Turn the overlay Off */
+		ovl_regs_plb->command = 0;
+		/* Always use buf 0 when turning the overlay off. */
+		ovl_context->ovl_buff = 0;
+		OS_FREE(ovl_cache_plb);
+		EMGD_TRACE_EXIT;
+		return IGD_SUCCESS;
+	}
+
+	/* Force value of y1 to even due hardware expects even number */
+	dest_rect->y1 &= ~1;
+	dest_rect->y2 = (dest_rect->y2 + 1) & ~1;
+	dest_rect->x1 &= ~1;
+	dest_rect->x2 = (dest_rect->x2 + 1) & ~1;
+
+	/*************************************************************************
+	 * Copy the information passed in to the HW overlay structure
+	 *************************************************************************/
+	/* Zero the config and command, since they will be OR'ed in with data
+	 * below */
+	ovl_cache_plb->config = 0;
+	ovl_cache_plb->command = 0;
+
+	/* Set overlay to the proper pipe */
+	if (1 == PIPE(display)->pipe_num) {
+		/* This is pipe B */
+		ovl_cache_plb->config |= 1 << 18;
+	}
+
+	/* Interleaved/progressive and Odd/Even if interleaved */
+	if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+		ovl_cache_plb->command |= OVL_CMD_FIELD_MODE;
+		/* Need to enable FIELD SYNC OVERLAY FLIP in field mode. */
+		ovl_cache_plb->command |= OVL_CMD_FIELD_SYNC_FLIP;
+		/* HSD# 203821 Mplayer outputs single one buffer including both even and odd fields */
+		if (flags & IGD_OVL_ALTER_FLIP_ODD) {
+			ovl_cache_plb->command |= OVL_CMD_ACT_FLD1;
+			/* HSD# 203821 To display odd field, starts from first odd field. */
+			if (0 == src_rect->y1 & 1) {
+				src_rect->y1 += 1;
+			}
+		} else {
+			ovl_cache_plb->command |= OVL_CMD_ACT_FLD0;
+			/* HSD# 203821 To display even field, starts from first even field. */
+			if (0 != src_rect->y1 & 1) {
+				src_rect->y1 += 1;
+			}
+		}
+	} else {
+		ovl_cache_plb->command |= OVL_CMD_FRAME_MODE;
+	}
+
+	/* Dest rect information */
+	ovl_cache_plb->dest_pos_x_left        = (unsigned short)dest_rect->x1;
+	ovl_cache_plb->dest_pos_y_top         = (unsigned short)dest_rect->y1;
+	ovl_cache_plb->dest_width_x           =
+		(unsigned short)(dest_rect->x2 - dest_rect->x1);
+	ovl_cache_plb->dest_height_y          =
+		(unsigned short)(dest_rect->y2 - dest_rect->y1);
+
+	/* Src rect and surface information */
+
+	ret = ovl_update_src_ptr_plb(display, ovl_cache_plb, src_surf, src_rect);
+	if (ret) {
+		OS_FREE(ovl_cache_plb);
+		EMGD_ERROR_EXIT("Overlay updating src pointers failed");
+		return ret;
+	}
+
+	ret = ovl_update_src_plb(display, ovl_cache_plb, src_surf, src_rect);
+	if (ret) {
+		OS_FREE(ovl_cache_plb);
+		EMGD_ERROR_EXIT("Overlay updating src failed");
+		return ret;
+	}
+
+	/* Scaling information including Vertical downscaling.
+	 * Scaling should be guaranteed to work, since if the scale is not
+	 * supported, it should have already been blended to a supported scale. */
+	ret = ovl_update_scale_plb(ovl_cache_plb, src_surf, src_rect, dest_rect,
+		flags);
+	if (ret) {
+		OS_FREE(ovl_cache_plb);
+		EMGD_ERROR_EXIT("Overlay updating scaling failed");
+		return ret;
+	}
+
+	/* Color control information */
+	ret = ovl_update_video_quality_plb(ovl_cache_plb, src_surf,
+		&ovl_info->video_quality);
+	if (ret) {
+		OS_FREE(ovl_cache_plb);
+		EMGD_ERROR_EXIT("Overlay video quality failed");
+		return ret;
+	}
+	ret = ovl_update_gamma_plb(display, &ovl_info->gamma);
+	if (ret) {
+		OS_FREE(ovl_cache_plb);
+		EMGD_ERROR_EXIT("Overlay gamma failed");
+		return ret;
+	}
+
+	/* Destination color key */
+	EMGD_DEBUG("Color key.flags: 0x%lx", ovl_info->color_key.flags);
+	if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+		EMGD_DEBUG("Overlay Enable Dest Color Key");
+		/* The mask and color key are different for the different
+		 * pixel formats */
+		ovl_cache_plb->dest_ckey_val = convert_color_key_to_hw(
+			PLANE(display)->fb_info->pixel_format,
+			ovl_info->color_key.dest);
+		ovl_cache_plb->dest_ckey_mask = convert_color_key_to_mask(
+			PLANE(display)->fb_info->pixel_format,
+			ovl_info->color_key.dest);
+		ovl_cache_plb->dest_ckey_mask |= 0x80000000;
+	} else {
+		EMGD_DEBUG("Overlay Disable Dest Color Key");
+		ovl_cache_plb->dest_ckey_mask = 0x00000000;
+	}
+
+	/* Source Color key */
+	if (ovl_info->color_key.flags & IGD_OVL_SRC_COLOR_KEY_ENABLE) {
+		EMGD_DEBUG("Overlay Enable Src Color Key");
+		ovl_cache_plb->source_ckey_high = convert_color_key_to_hw(
+			src_surf->pixel_format,
+			ovl_info->color_key.src_hi);
+		ovl_cache_plb->source_ckey_high = rgb_to_gbr(
+			src_surf->pixel_format,
+			ovl_cache_plb->source_ckey_high);
+
+		ovl_cache_plb->source_ckey_low = convert_color_key_to_hw(
+			src_surf->pixel_format,
+			ovl_info->color_key.src_lo);
+		ovl_cache_plb->source_ckey_low = rgb_to_gbr(
+			src_surf->pixel_format,
+			ovl_cache_plb->source_ckey_low);
+
+		ovl_cache_plb->source_ckey_mask = 0x07000000;
+	} else {
+		EMGD_DEBUG("Overlay Disable Src Color Key");
+		ovl_cache_plb->source_ckey_mask = 0x00000000;
+	}
+
+	/* Coefficients - Must be after Scaling */
+	ret = ovl_update_coeff_plb(ovl_cache_plb, src_surf, src_rect, dest_rect, flags);
+	if (ret) {
+		OS_FREE(ovl_cache_plb);
+		EMGD_ERROR_EXIT("Overlay updating coefficient failed");
+		return ret;
+	}
+
+	/* Phase information - Must be after Coefficients */
+	ret = ovl_update_phase_plb(ovl_cache_plb, src_surf, src_rect);
+	if (ret) {
+		OS_FREE(ovl_cache_plb);
+		EMGD_ERROR_EXIT("Overlay updating phase failed");
+		return ret;
+	}
+
+	/* General overlay information.  Turn the overlay on and alternate
+	 * between Buffer 0 and Buffer 1. */
+	ovl_cache_plb->command = (ovl_cache_plb->command & 0xfffffff3) |
+			ovl_context->ovl_buff | 1;
+	ovl_context->ovl_buff ^= OVL_CMD_ACT_BUF1;
+
+	/* Dump out the Overlay Update Registers if debugging */
+	EMGD_VERBOSE(hal.dump_overlay_regs, ovl_dump_regs_plb(ovl_regs_plb));
+
+	OS_MEMCPY(ovl_regs_plb, ovl_cache_plb, sizeof(ovl_reg_image_plb_t));
+	OS_FREE(ovl_cache_plb);
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+#else /* Else OVL_PLB_CACHE_QUICK_SWAP */
+
+/* Poulsbo overlay cache structure */
+static ovl_plb_cache_t ovl_cache;
+
+/* Flag to signal the cache is invalid and needs
+ * to be re-initialized */
+static int ovl_cache_needs_init = TRUE;
+
+static unsigned int ovl_update_regs_plb(
+	igd_display_context_t *display,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	igd_ovl_info_t      *ovl_info,
+	unsigned int         flags)
+{
+	ovl_reg_image_plb_t *ovl_regs_plb,
+		            *ovl_cache_regs;
+	unsigned int         cache_changed;
+	int                  ret;
+
+	EMGD_TRACE_ENTER;
+
+	/* get the pointers to the real regs, and our cached copy of them */
+	ovl_regs_plb = phys_to_virt(ovl_context->reg_update_phys);
+	ovl_cache_regs = &ovl_cache.ovl_regs;
+
+	/* Fast path for turning off overlay. No need for cache */
+	if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
+
+		/* Turn the overlay Off */
+		ovl_regs_plb->command = 0;
+
+		/* if we were using the cache, turn it off there too */
+		if (!ovl_cache_needs_init) {
+			ovl_cache.ovl_regs.command = 0;
+		}
+
+		/* Reset the cache */
+		ovl_cache_needs_init = TRUE;
+
+		/* Always use buf 0 when turning the overlay off. */
+		ovl_context->ovl_buff = 0;
+		EMGD_TRACE_EXIT;
+		return IGD_SUCCESS;
+	}
+
+	/* Force value to even due hardware expects even number */
+	dest_rect->y1 &= ~1;
+	dest_rect->y2 = (dest_rect->y2 + 1) & ~1;
+	dest_rect->x1 &= ~1;
+	dest_rect->x2 = (dest_rect->x2 + 1) & ~1;
+
+	/* Init the cache if necessary */
+	if (ovl_cache_needs_init) {
+
+
+		/* Force every cache check to miss */
+		OS_MEMSET(&ovl_cache, 0, sizeof(ovl_plb_cache_t));
+
+		/* We just set our cached flags to 0, which might accidently
+		 * match up with "OFF" for some important incoming flag
+		 * bits, causing us to think we already handled them when
+		 * we didn't.  So set our cached flags to the exact
+		 * opposite of the incoming flags, which will force
+		 * us to test and handle every single bit, regardless
+		 * of whether it is on or off. */
+		ovl_cache.flags = ~flags;
+
+		/* init our cached registers */
+		OS_MEMCPY(ovl_cache_regs,
+			  ovl_regs_plb,
+			  sizeof(ovl_reg_image_plb_t));
+
+		/* initialization complete */
+		ovl_cache_needs_init = FALSE;
+	}
+
+	/* See what has changed in the cache */
+	cache_changed = get_cache_changes_plb (src_surf,
+					   src_rect,
+					   dest_rect,
+					   ovl_info,
+					   flags,
+					   &ovl_cache);
+
+	/* Perhaps the biggest challenge of caching the overlay
+	 * state is what to do with the command and config regs.
+	 * Normally we would clear command and config to 0 here,
+	 * and let the update process set only the bits that are
+	 * needed.  But doing this would invalidate our cache.
+	 * Instead we are relying on the above call to
+	 * get_cache_changes() to clear those bits in command
+	 * and config that will be changing */
+
+	/* Set overlay to the proper pipe */
+	/* it is cheaper to just set this, than to test it and set it. */
+	if (1 == PIPE(display)->pipe_num) {
+		/* This is pipe B */
+		ovl_cache_regs->config |= 1 << 18;
+	} else {
+		ovl_cache_regs->config &= ~(1 << 18);
+	}
+
+	if (cache_changed & IGD_OVL_PLB_UPDATE_FLAGS) {
+
+		/* Interleaved/progressive and Odd/Even if interleaved. */
+		if (flags & IGD_OVL_ALTER_INTERLEAVED) {
+			ovl_cache_regs->command |= OVL_CMD_FIELD_MODE;
+			/* enable FIELD SYNC OVERLAY FLIP in field mode. */
+			ovl_cache_regs->command |= OVL_CMD_FIELD_SYNC_FLIP;
+			/* HSD# 203821 Mplayer outputs single one buffer including both even and odd fields */
+			if (flags & IGD_OVL_ALTER_FLIP_ODD) {
+				ovl_cache_regs->command |= OVL_CMD_ACT_FLD1;
+				/* HSD# 203821 To display odd field, starts from first odd field. */
+				if (0 == (src_rect->y1 & 1)) {
+					src_rect->y1 += 1;
+				}
+			} else {
+				ovl_cache_regs->command |= OVL_CMD_ACT_FLD0;
+				/* HSD# 203821 To display even field, starts from first even field. */
+				if (0 != (src_rect->y1 & 1)) {
+					src_rect->y1 += 1;
+				}	
+			}
+		} else {
+			ovl_cache_regs->command |= OVL_CMD_FRAME_MODE;
+		}
+	}
+
+	/* Has our destination rectangle changed? */
+	if (cache_changed & IGD_OVL_PLB_UPDATE_DEST) {
+		ovl_cache_regs->dest_pos_x_left  =
+			(unsigned short) dest_rect->x1;
+		ovl_cache_regs->dest_pos_y_top   =
+			(unsigned short) dest_rect->y1;
+		ovl_cache_regs->dest_width_x     =
+			(unsigned short) (dest_rect->x2 - dest_rect->x1);
+		ovl_cache_regs->dest_height_y    =
+			(unsigned short) (dest_rect->y2 - dest_rect->y1);
+
+	}
+
+	/* Always update the source pointers every frame */
+	ret = ovl_update_src_ptr_plb(display,
+				 ovl_cache_regs,
+				 src_surf,
+				 src_rect);
+	if (ret) {
+		/* Not good. Invalidate the entire cache and bail. */
+		ovl_cache_needs_init = TRUE;
+		EMGD_ERROR_EXIT("Overlay updating src pointers failed");
+		return ret;
+	}
+
+	/* Did either the Src rect or surface change? */
+	if (cache_changed & (IGD_OVL_PLB_UPDATE_SURF |
+			     IGD_OVL_PLB_UPDATE_SRC  ) ) {
+
+		ret = ovl_update_src_plb(display,
+					 ovl_cache_regs,
+					 src_surf,
+					 src_rect);
+		if (ret) {
+			/* Not good. Invalidate the entire cache and bail. */
+			ovl_cache_needs_init = TRUE;
+			EMGD_ERROR_EXIT("Overlay updating src failed");
+			return ret;
+		}
+	}
+
+	/* Scaling information including Vertical downscaling.
+	 * Scaling should be guaranteed to work, since if the scale
+	 * is not supported, it should have already been blended
+	 * to a supported scale. */
+	if ( cache_changed & (IGD_OVL_PLB_UPDATE_SRC  |
+			      IGD_OVL_PLB_UPDATE_SURF |
+			      IGD_OVL_PLB_UPDATE_DEST  |
+			      IGD_OVL_PLB_UPDATE_FLAGS) ) {
+
+		ret = ovl_update_scale_plb(ovl_cache_regs,
+					   src_surf,
+					   src_rect,
+					   dest_rect,
+					   flags);
+		if (ret) {
+			/* Not good. Invalidate the entire cache and bail. */
+			ovl_cache_needs_init = TRUE;
+			EMGD_ERROR_EXIT("Overlay updating scaling failed");
+			return ret;
+		}
+	}
+
+	/* Did video quality change? */
+	if (cache_changed & (IGD_OVL_PLB_UPDATE_VQ   |
+			     IGD_OVL_PLB_UPDATE_SURF ) ) {
+		/* Color control information */
+
+		ret = ovl_update_video_quality_plb(ovl_cache_regs, src_surf,
+						   &ovl_info->video_quality);
+		if (ret) {
+			/* Not good. Invalidate the entire cache and bail. */
+			ovl_cache_needs_init = TRUE;
+			EMGD_ERROR_EXIT("Overlay video quality failed");
+			return ret;
+		}
+	}
+
+	/* Did gamma change? */
+	if (cache_changed & IGD_OVL_PLB_UPDATE_GAMMA) {
+
+		ret = ovl_update_gamma_plb(display, &ovl_info->gamma);
+		if (ret) {
+			/* Not good. Invalidate the entire cache and bail. */
+			ovl_cache_needs_init = TRUE;
+			EMGD_ERROR_EXIT("Overlay gamma failed");
+			return ret;
+		}
+	}
+
+	/* Did color key change? */
+	if (cache_changed & IGD_OVL_PLB_UPDATE_COLORKEY) {
+
+		/* Destination color key */
+		EMGD_DEBUG("Color key.flags: 0x%lx", ovl_info->color_key.flags);
+		if (ovl_info->color_key.flags & IGD_OVL_DST_COLOR_KEY_ENABLE) {
+
+			EMGD_DEBUG("Overlay Enable Dest Color Key");
+			/* The mask and color key are different for the
+			 * different pixel formats */
+			ovl_cache_regs->dest_ckey_val =
+				convert_color_key_to_hw(
+					PLANE(display)->fb_info->pixel_format,
+					ovl_info->color_key.dest);
+			ovl_cache_regs->dest_ckey_mask =
+				convert_color_key_to_mask(
+					PLANE(display)->fb_info->pixel_format,
+					ovl_info->color_key.dest);
+			ovl_cache_regs->dest_ckey_mask |= 0x80000000;
+		} else {
+			EMGD_DEBUG("Overlay Disable Dest Color Key");
+			ovl_cache_regs->dest_ckey_mask = 0x00000000;
+		}
+
+		/* Source Color key */
+		if (ovl_info->color_key.flags & IGD_OVL_SRC_COLOR_KEY_ENABLE) {
+
+			EMGD_DEBUG("Overlay Enable Src Color Key");
+			ovl_cache_regs->source_ckey_high =
+				convert_color_key_to_hw(
+					src_surf->pixel_format,
+					ovl_info->color_key.src_hi);
+			ovl_cache_regs->source_ckey_high =
+				rgb_to_gbr(src_surf->pixel_format,
+					   ovl_cache_regs->source_ckey_high);
+
+			ovl_cache_regs->source_ckey_low =
+				convert_color_key_to_hw(
+					src_surf->pixel_format,
+					ovl_info->color_key.src_lo);
+			ovl_cache_regs->source_ckey_low =
+				rgb_to_gbr(src_surf->pixel_format,
+					   ovl_cache_regs->source_ckey_low);
+
+			ovl_cache_regs->source_ckey_mask = 0x07000000;
+		} else {
+			EMGD_DEBUG("Overlay Disable Src Color Key");
+			ovl_cache_regs->source_ckey_mask = 0x00000000;
+		}
+	} /* end color key changes */
+
+
+	/* Coefficients - Must be after Scaling */
+	if (cache_changed & (IGD_OVL_PLB_UPDATE_SRC   |
+			     IGD_OVL_PLB_UPDATE_SURF  |
+			     IGD_OVL_PLB_UPDATE_DEST  |
+			     IGD_OVL_PLB_UPDATE_FLAGS ) ) {
+
+		    ret = ovl_update_coeff_plb(ovl_cache_regs,
+					       src_surf,
+					       src_rect,
+					       dest_rect,
+					       flags);
+		    if (ret) {
+			    /* Not good. Invalidate entire cache and bail. */
+			    ovl_cache_needs_init = TRUE;
+			    EMGD_ERROR_EXIT("Overlay update coefficient failed");
+			    return ret;
+		    }
+	    }
+
+	    /* Phase information - Must be after Coefficients */
+	    if (cache_changed & (IGD_OVL_PLB_UPDATE_SRC |
+			      IGD_OVL_PLB_UPDATE_SURF ) ) {
+
+		    ret = ovl_update_phase_plb(ovl_cache_regs,
+					       src_surf,
+					       src_rect);
+		    if (ret) {
+			    /* Not good. Invalidate entire cache and bail. */
+			    ovl_cache_needs_init = TRUE;
+			    EMGD_ERROR_EXIT("Overlay updating phase failed");
+			    return ret;
+		    }
+	    }
+
+	    /* General overlay information.  Turn the overlay on and alternate
+	     * between Buffer 0 and Buffer 1. */
+	    ovl_cache_regs->command = (ovl_cache_regs->command & 0xfffffff3) |
+					ovl_context->ovl_buff | 1;
+	    ovl_context->ovl_buff ^= OVL_CMD_ACT_BUF1;
+
+	    /* Dump out the Overlay Update Registers if debugging */
+	    EMGD_VERBOSE(hal.dump_overlay_regs, ovl_dump_regs_plb(ovl_regs_plb));
+
+	    /* Finally, transfer the cached regs to the real regs */
+	    OS_MEMCPY(ovl_regs_plb,
+		      ovl_cache_regs,
+		      sizeof(ovl_reg_image_plb_t));
+
+	    EMGD_TRACE_EXIT;
+	    return IGD_SUCCESS;
+}
+
+#endif /* End if OVL_PLB_CACHE_QUICK_SWAP */
+
+static unsigned int ovl_send_instr_plb(
+	igd_display_context_t     *display,
+	unsigned int      flags)
+{
+	unsigned char * mmio = MMIO(display);
+	unsigned long tmp;
+
+	EMGD_TRACE_ENTER;
+
+	if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_ON) {
+
+		ovl_context->state = OVL_STATE_ON;
+		/*
+		 * If Overlay + FB Blend is requested and the FB is xRGB
+		 * turn on the ARGB format.
+		 */
+		if(ovl_context->fb_blend_ovl) {
+			tmp = EMGD_READ32(mmio +  PLANE(display)->plane_reg);
+			if((tmp & 0x3c000000) == 0x18000000) {
+				EMGD_WRITE32(tmp | 0x1c000000, mmio +  PLANE(display)->plane_reg);
+				tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 4);
+				EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 4);
+			}
+		}
+
+	} else {
+
+		if (ovl_context->fb_blend_ovl) {
+			tmp = EMGD_READ32(mmio +  PLANE(display)->plane_reg);
+			if((tmp & 0x3c000000) == 0x1c000000) {
+				tmp = tmp & 0xc3FFFFFF;
+				EMGD_WRITE32(tmp | 0x18000000, mmio +  PLANE(display)->plane_reg);
+				tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 4);
+				EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 4);
+				OS_SLEEP(100);
+			}
+		}
+
+		OS_SLEEP(1);
+
+		/* if overlay is being turned OFF - ensure it's ON first */
+		if (ovl_context->state == OVL_STATE_OFF) {
+			/* Overlay is already off, no need to turn it off again */
+			EMGD_TRACE_EXIT;
+			return IGD_SUCCESS;
+		}
+
+		ovl_context->state = OVL_STATE_OFF;
+	}
+
+	/* Write the address of the memory buffer to the Overlay Update
+	 * Address Register causes the HW to load the new values from the
+	 * memory on the next VBLANK */
+	EMGD_WRITE32((ovl_context->reg_update_phys | 0x1), mmio + 0x30000);
+
+	ovl_context->sync = 0;
+
+	display->context->dispatch.sync(display,
+		IGD_PRIORITY_NORMAL,
+		&ovl_context->sync,
+		IGD_SYNC_NONBLOCK);
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
+
+
+
+
+static int alter_ovl_plb(igd_display_context_t *display,
+			 igd_surface_t       *src_surf,
+			 igd_rect_t          *src_rect,
+			 igd_rect_t          *dest_rect,
+			 igd_ovl_info_t      *ovl_info,
+			 unsigned int         flags)
+{
+	int ret;
+
+	EMGD_TRACE_ENTER;
+	/* Dump overlay parameters for debugging */
+	/*
+	printk (KERN_ERR " alter_ovl_plb  Entry."
+		"offset=0x%X "
+		"pitch=%d "
+		"width=%d "
+		"height=%d \n"
+		"pixel_format=0x%X "
+		"flags=0x%X "
+		"virt_addr=0x%X "
+		"pvr2d_mem_info=0x%X "
+		"pvr2d_context_h=0x%X "
+		"hPVR2DFlipChain=0x%X \n"
+		"src_x1=%d "
+		"src_x2=%d "
+		"src_y1=%d "
+		"src_y2=%d "
+		"src width=%d "
+		"src height=%d \n"
+		"dest_x1=%d "
+		"dest_x2=%d "
+		"dest_y1=%d "
+		"dest_y2=%d "
+		"dest width=%d "
+		"dest height=%d \n"
+		"color_key.src_lo=0x%X "
+		"color_key.src_hi=0x%X "
+		"color_key.dest=0x%X "
+		"color_key.flags=0x%X "
+		"flags=0x%X "
+		,
+		(unsigned int) src_surf->offset ,
+		(unsigned int) src_surf->pitch ,
+		(unsigned int) src_surf->width ,
+		(unsigned int) src_surf->height ,
+		(unsigned int) src_surf->pixel_format ,
+		(unsigned int) src_surf->flags ,
+		(unsigned int) src_surf->virt_addr ,
+		(unsigned int) src_surf->pvr2d_mem_info ,
+		(unsigned int) src_surf->pvr2d_context_h ,
+		(unsigned int) src_surf->hPVR2DFlipChain ,
+		(unsigned int) src_rect->x1,
+		(unsigned int) src_rect->x2,
+		(unsigned int) src_rect->y1,
+		(unsigned int) src_rect->y2,
+		(unsigned int) (src_rect->x2 - src_rect->x1),
+		(unsigned int) (src_rect->y2 - src_rect->y1),
+		(unsigned int) dest_rect->x1,
+		(unsigned int) dest_rect->x2,
+		(unsigned int) dest_rect->y1,
+		(unsigned int) dest_rect->y2,
+		(unsigned int) (dest_rect->x2 - dest_rect->x1),
+		(unsigned int) (dest_rect->y2 - dest_rect->y1),
+		(unsigned int) ovl_info->color_key.src_lo,
+		(unsigned int) ovl_info->color_key.src_hi,
+		(unsigned int) ovl_info->color_key.dest,
+		(unsigned int) ovl_info->color_key.flags,
+		(unsigned int) flags
+		);
+	*/
+	/* Dump overlay surface contents, for debugging */
+	/*
+	if (flags & IGD_OVL_ALTER_ON)
+	{
+		int i;
+		unsigned char *ptr = src_surf->virt_addr;
+
+		for (i = 0; i<10; ++i) {
+			printk(KERN_ERR
+			       "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X"
+			       "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X"
+			       "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X"
+			       "%2X%2X%2X%2X%2X%2X%2X%2X%2X%2X",
+			       ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],
+			       ptr[5],ptr[6],ptr[7],ptr[8],ptr[9],
+			       ptr[10],ptr[11],ptr[12],ptr[13],ptr[14],
+			       ptr[15],ptr[16],ptr[17],ptr[18],ptr[19],
+			       ptr[20],ptr[21],ptr[22],ptr[23],ptr[24],
+			       ptr[25],ptr[26],ptr[27],ptr[28],ptr[29],
+			       ptr[30],ptr[31],ptr[32],ptr[33],ptr[34],
+			       ptr[35],ptr[36],ptr[37],ptr[38],ptr[39]);
+			ptr += src_surf->pitch;
+		}
+	}
+	*/
+
+	/* Check to ensure the overlay can be used given the current mode as
+	 * well as what the IAL is asking for.  If not return an error. */
+	ret = ovl_check_plb(display, src_surf, src_rect, dest_rect, ovl_info,
+			    flags);
+	if (ret) {
+		EMGD_ERROR_EXIT("Overlay Check failed");
+		return ret;
+	}
+
+	/* Check if last flip is still pending.
+	 * This is necessary for the following reasons:
+	 *    - If the previous instructions have not been processed, then the
+	 *      ovl_regs_plb is still in use and can not be overwritten.
+	 */
+	if ((FALSE == query_ovl_plb(
+				    (igd_display_h)display,
+				    IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE)) &&
+	    (flags & IGD_OVL_ALTER_ON)) {
+		/* Only return an error if the overlay is on.  If turning it off,
+		 * allow it to continue, since something may have failed and we
+		 * should try our best to turn the overlay off. */
+		EMGD_ERROR_EXIT("Query Overlay failed");
+		return -IGD_ERROR_HWERROR;
+	}
+
+	/* Update all Overlay Update Registers */
+	ret = ovl_update_regs_plb(display, src_surf, src_rect,
+				  dest_rect, ovl_info,
+				  flags);
+	if (ret) {
+		EMGD_ERROR_EXIT("Overlay Update Registers failed");
+		return ret;
+	}
+
+	/* Send the instructions to the command queue */
+	ret = ovl_send_instr_plb(display, flags);
+
+	EMGD_TRACE_EXIT;
+	return ret;
+}
+
+
+
+static int query_ovl_plb(igd_display_h display_h,
+	unsigned int flags)
+{
+	igd_display_context_t *display = (igd_display_context_t *)display_h;
+	os_alarm_t timeout;
+
+	EMGD_TRACE_ENTER;
+
+	switch (flags) {
+
+	case IGD_OVL_QUERY_IS_HW_SUPPORTED:
+		/* This is the first overlay, so HW overlay is supported */
+		break;
+
+	case IGD_OVL_QUERY_IS_LAST_FLIP_DONE:
+		/* If there no sync to wait on, then the last flip is done, and the
+		 * Register Update has occured, simply return TRUE (Flip done).
+		 */
+		/*if (!(ovl_context->sync)) {
+			return TRUE;
+		}*/
+
+		/* Check to see if the last flip instruction has been executed.  If not
+		 * return FALSE (Flip not done). */
+		/*if(display->context->dispatch.sync(
+			display,
+			IGD_PRIORITY_NORMAL,
+			&ovl_context->sync,
+			IGD_SYNC_NONBLOCK)) {
+			EMGD_DEBUG("Overlay Sync Check - Flip not done");
+			return FALSE;
+		}*/
+
+		/* Check to see if the register update is complete.  If not return
+		 * FALSE (Flip not done). */
+		if(!(EMGD_READ32(MMIO(display) + 0x30008) & 0x80000000)) {
+			EMGD_DEBUG("Overlay Status Check - Register Update not done");
+			return FALSE;
+		}
+
+		/* Now that we know the last flip is done and the register update is
+		 * complete, set the sync to 0 and return TRUE (Flip done). */
+		ovl_context->sync = 0;
+		break;
+
+	case IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE:
+		/* Wait for 200 milliseconds for the last flip to complete.  If not
+		 * done in that time, there is likely a hardware problem so return
+		 * FALSE. */
+		timeout = OS_SET_ALARM(200);
+		do {
+			if (TRUE ==
+				query_ovl_plb(display_h, IGD_OVL_QUERY_IS_LAST_FLIP_DONE)) {
+				EMGD_TRACE_EXIT;
+				return TRUE;
+			}
+		} while (!OS_TEST_ALARM(timeout));
+		EMGD_ERROR_EXIT("Timeout waiting for last flip done");
+		return FALSE;
+		break;
+	case IGD_OVL_QUERY_IS_GAMMA_SUPPORTED:
+		return TRUE;
+		break;
+	case IGD_OVL_QUERY_IS_VIDEO_PARAM_SUPPORTED:
+		return TRUE;
+		break;
+	}
+
+	EMGD_TRACE_EXIT;
+	return TRUE;
+}
+
+static int query_max_size_ovl_plb(
+	igd_display_h display_h,
+	unsigned long pf,
+	unsigned int *max_width,
+	unsigned int *max_height)
+{
+	ovl_chipset_plb_t *ovl_chip;
+
+	EMGD_TRACE_ENTER;
+
+	ovl_chip = ovl_chipset_plb;
+	*max_width = 0;
+	*max_height = 0;
+	while(ovl_chip->num_linebuf != OVL_CONFIG_NO_LINE_BUFF){
+		if(((pf & IGD_PF_MASK) == ovl_chip->pixel_format) &&
+			(ovl_chip->max_width > *max_width)) {
+			*max_width = ovl_chip->max_width;
+			*max_height = ovl_chip->max_height;
+		}
+		ovl_chip++;
+	}
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb_cache.c b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb_cache.c
new file mode 100644
index 0000000..d05c475
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb_cache.c
@@ -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/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb_cache.h b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb_cache.h
new file mode 100644
index 0000000..b8bb2ef
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_plb_cache.h
@@ -0,0 +1,161 @@
+/*
+ *----------------------------------------------------------------------------
+ * Filename: ovl_plb_cache.h
+ * $Revision: 1.5 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the internal header file for overlay caching. It should be not be
+ *  by any other module besides the overlay module itself.
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _OVL_PLB_CACHE_H
+#define _OVL_PLB_CACHE_H
+
+#include <rb.h>
+#include "ovl_regs_plb.h"
+#include "ovl2_regs_plb.h"
+
+/* Turns the overlay cache on and off. */
+#define OVL_PLB_CACHE_QUICK_SWAP
+
+
+/*
+ * In order to cache the overlay registers we need a structure
+ * that defines and wraps them.  We already have one for the primary
+ * display, called ovl_reg_image_plb_t.
+ * Here we define a structure for the secondary display
+ */
+
+typedef struct _ovl2_reg_plb_cache{
+	unsigned int control;
+	unsigned int start;
+	unsigned int plane_control;
+	unsigned int plane_start;
+
+	unsigned int pitch;
+	unsigned int dest_rect_x1y1;
+	unsigned int dest_rect_x2y2;
+	unsigned int cont_bright;
+	unsigned int satn_hue;
+	unsigned int gamma_regs[OVL2_TOTAL_GAMMA_REG];
+	unsigned int colorkey_hw;
+	unsigned int colorkey_mask;
+	unsigned int ckey_high;
+	unsigned int ckey_low;
+	unsigned int ckey_enable;
+
+} ovl2_reg_plb_cache_t;
+
+#define MMIO_OFFSET_PLB2_PITCH          0x72188
+#define MMIO_OFFSET_PLB2_DEST_RECT_X1Y1 0x7218C
+#define MMIO_OFFSET_PLB2_DEST_RECT_X2Y2 0x72190
+#define MMIO_OFFSET_PLB2_CONT_BRIGHT    0x721D0
+#define MMIO_OFFSET_PLB2_SATN_HUE       0x721D4
+#define MMIO_OFFSET_PLB2_COLORKEY_HW    0x14
+#define MMIO_OFFSET_PLB2_COLORKEY_MASK  0x18
+#define MMIO_OFFSET_PLB2_CKEY_LOW       0x72194
+#define MMIO_OFFSET_PLB2_CKEY_HIGH      0x721a0
+#define MMIO_OFFSET_PLB2_CKEY_ENABLE    0x72198
+#define MMIO_OFFSET_PLB2_CONTROL        0x72180
+#define MMIO_OFFSET_PLB2_START          0x72184
+
+
+/*
+ * This stucture caches the overlay state, so we don't have to
+ * re-program everything for every single frame
+ */
+typedef struct _ovl_plb_cache {
+	igd_surface_t        src_surf;
+	igd_rect_t           src_rect;
+	igd_rect_t           dest_rect;
+	igd_ovl_info_t       ovl_info;
+	unsigned int         flags;
+	ovl_reg_image_plb_t  ovl_regs;
+	ovl2_reg_plb_cache_t ovl2_regs;
+} ovl_plb_cache_t, *povl_plb_cache_t;
+
+
+/* Flags for things that might have changed in the cache */
+#define IGD_OVL_PLB_UPDATE_DEST     (1 << 0)
+#define IGD_OVL_PLB_UPDATE_SRC      (1 << 1)
+#define IGD_OVL_PLB_UPDATE_SURF     (1 << 2)
+#define IGD_OVL_PLB_UPDATE_INFO     (1 << 3)
+#define IGD_OVL_PLB_UPDATE_FLAGS    (1 << 4)
+#define IGD_OVL_PLB_UPDATE_VQ       (1 << 5)
+#define IGD_OVL_PLB_UPDATE_GAMMA    (1 << 6)
+#define IGD_OVL_PLB_UPDATE_COLORKEY (1 << 7)
+
+
+/*
+ * Caching helper functions.  Implemented in ovl_plb.c, but used by
+ * the ovl2 and micro_ovl modules as well.
+ */
+
+/* Tells if a rectangle has changed */
+int is_changed_rect(igd_rect_t *old_rect, igd_rect_t *new_rect);
+
+/* Tells if a surface has changed */
+int is_changed_surf(igd_surface_t *old_surf, igd_surface_t *new_surf);
+
+/* Tells if the color key has changed */
+ int is_changed_color_key(igd_ovl_info_t *old_info, igd_ovl_info_t *new_info) ;
+
+/* Tells if the video quality has changed */
+int is_changed_vq(igd_ovl_info_t *old_info, igd_ovl_info_t *new_info);
+
+/* Tells if the gamma has changed */
+int is_changed_gamma(igd_ovl_info_t *old_info, igd_ovl_info_t *new_info);
+
+/* Copies a source rectangle to the cache */
+void copy_src_rect_plb(igd_rect_t *src_rect, povl_plb_cache_t ovl_cache);
+
+/* Copies a dest rectangle to the cache */
+void copy_dest_rect_plb(igd_rect_t *dest_rect, povl_plb_cache_t ovl_cache);
+
+/* Copies a surface to the cache */
+void copy_surf_plb(igd_surface_t *src_surf, povl_plb_cache_t ovl_cache);
+
+/* Copies the color key to the cache */
+void copy_color_key_plb(igd_ovl_info_t *ovl_info, povl_plb_cache_t ovl_cache);
+
+/* Copies the video quality info to the cache */
+void copy_vq_plb(igd_ovl_info_t *ovl_info, povl_plb_cache_t ovl_cache);
+
+/* Copies the gamma to the cache */
+void copy_gamma_plb(igd_ovl_info_t *ovl_info, povl_plb_cache_t ovl_cache);
+
+/* Checks to see what, if anything has changed.
+ * Clears bits in the command and config register that are invalid.
+ * Returns a set of flags telling what changed */
+unsigned int get_cache_changes_plb(
+			       igd_surface_t  *src_surf,
+			       igd_rect_t     *src_rect,
+			       igd_rect_t     *dest_rect,
+			       igd_ovl_info_t *ovl_info,
+			       unsigned int    flags,
+			       povl_plb_cache_t ovl_cache);
+
+
+
+#endif /* _OVL_PLB_CACHE_H */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_regs_plb.h b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_regs_plb.h
new file mode 100644
index 0000000..34b24c4
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/plb/ovl_regs_plb.h
@@ -0,0 +1,185 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_regs_plb.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the internal header file for overlay. It should be not be
+ *  by any other module besides the overlay module itself. It contains the
+ *  neccessary hardware virtualized register dependant information including
+ *  values, structures and addresses specifically for the Napa core
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef OVL_REGS_PLB_H_
+#define OVL_REGS_PLB_H_
+
+/* Overlay Update Register Image Structure.*/
+typedef struct _ovl_reg_image_plb{
+
+	volatile unsigned int			buffer0_yrgb_ptr;
+	volatile unsigned int			buffer1_yrgb_ptr;
+	volatile unsigned int			buffer0_u_ptr;
+	volatile unsigned int			buffer0_v_ptr;
+	volatile unsigned int			buffer1_u_ptr;
+	volatile unsigned int			buffer1_v_ptr;
+	volatile unsigned short			yrgb_stride;
+	volatile unsigned short			uv_stride;
+	volatile unsigned short			yrgb_vert_phase_field0;
+	volatile unsigned short			yrgb_vert_phase_field1;
+	volatile unsigned short			uv_vert_phase_field0;
+	volatile unsigned short			uv_vert_phase_field1;
+	volatile unsigned short			yrgb_hphase;
+	volatile unsigned short			uv_hphase;
+	volatile unsigned int			init_phase_shift;
+	volatile unsigned short			dest_pos_x_left;
+	volatile unsigned short			dest_pos_y_top;
+	volatile unsigned short			dest_width_x;
+	volatile unsigned short			dest_height_y;
+	volatile unsigned short			source_yrgb_width;
+	volatile unsigned short			source_uv_width;
+	volatile unsigned short			source_yrgb_width_swords;
+	volatile unsigned short			source_uv_width_swords;
+	volatile unsigned short			source_yrgb_height;
+	volatile unsigned short			source_uv_height;
+	volatile unsigned int			yrgb_scale;
+	volatile unsigned int			uv_scale;
+	volatile unsigned int			col_ctl_brt_con;
+	volatile unsigned int			col_ctl_sat_hue;
+	volatile unsigned int			dest_ckey_val;
+	volatile unsigned int			dest_ckey_mask;
+	volatile unsigned int			source_ckey_high;
+	volatile unsigned int			source_ckey_low;
+	volatile unsigned int			source_ckey_mask;
+	volatile unsigned int			config;
+	volatile unsigned int			command;
+	volatile unsigned int			reserved1;
+	volatile unsigned short			alpha_pos_x_left;
+	volatile unsigned short			alpha_pos_y_top;
+	volatile unsigned short			alpha_width_x;
+	volatile unsigned short			alpha_height_y;
+	volatile unsigned int			reserved2;
+	volatile unsigned int			reserved3;
+	volatile unsigned int			reserved4;
+	volatile unsigned int			reserved5;
+	volatile unsigned int			reserved6;
+	volatile unsigned int			reserved7;
+	volatile unsigned int			reserved8;
+	volatile unsigned int			reserved9;
+	volatile unsigned int			reserved10;
+	volatile unsigned int			reserved11;
+	volatile unsigned int			reserved11a; /*ovl_fast_horz_downscale;*/
+	volatile unsigned int			vert_downscale;
+	volatile unsigned int			reserved12[86];
+	volatile unsigned short			y_vert_coeff_single[52]; /*offset 0x200 --> 3*17/2 + 1*/
+	volatile unsigned int			reserved13[38];
+	volatile unsigned short			y_horz_coeff_single[86]; /*offset 0x300 --> 5*17/2 + 1*/
+	volatile unsigned int			reserved14[85];
+	volatile unsigned short			uv_vert_coeff_single[52]; /*offset 0x500 --> 3*17/2 + 1*/
+	volatile unsigned int			reserved15[38];
+	volatile unsigned short			uv_horz_coeff_single[52]; /*offset 0x600 --> 3*17/2 + 1*/
+	volatile unsigned int			reserved16[38];
+
+} ovl_reg_image_plb_t;
+
+/* Color Correction */
+#define OVL_YUV_COLOR_DEF_CONT_BRGHT    0x10c00fb
+#define OVL_YUV_COLOR_DEF_SATN_HUE      0x0000091
+#define OVL_RGB_COLOR_DEF_CONT_BRGHT    0x1000000
+#define OVL_RGB_COLOR_DEF_SATN_HUE      0x0000080
+
+/* Overlay Config */
+#define OVL_CONFIG_NO_LINE_BUFF     0xffffffff
+#define OVL_CONFIG_TWO_LINE_BUFF    0x00000000
+#define OVL_CONFIG_THREE_LINE_BUFF  0x00000001
+#define OVL_CONFIG_LINE_BUFF_MASK   0x00000001
+
+/* Overlay Command Definitions */
+/* 422 Swap */
+#define OVL_CMD_UV_SWAP				0x00004000
+#define OVL_CMD_Y_SWAP				0x00008000
+#define OVL_CMD_YUV_SWAP			0x0000C000
+
+/* Source Format */
+#define OVL_CMD_RGB_8888			0x00000400
+#define OVL_CMD_RGB_565				0x00000C00
+#define OVL_CMD_RGB_555				0x00000800
+#define OVL_CMD_YUV_NV12Alt			0x00001C00 /*planar NV12, Alternate?*/
+#define OVL_CMD_YUV_NV12			0x00002C00 /*planar NV12*/
+#define OVL_CMD_YUV_422				0x00002000 /*packed YUV422*/
+#define OVL_CMD_YUV_411				0x00002400 /*packed YUV411*/
+#define OVL_CMD_YUV_420P			0x00003000 /*planar YUV420*/
+#define OVL_CMD_YUV_422P			0x00003400 /*planar YUV422*/
+#define OVL_CMD_YUV_410P			0x00003800 /*planar YUV410*/
+#define OVL_CMD_YUV_444P			0x00003C00 /*planar YUV444*/
+#define OVL_CMD_SRC_FMT_MASK		0x00003C00 /*mask for above*/
+
+/* Flip Type */
+#define OVL_CMD_FRAME_MODE          0x00000000
+#define OVL_CMD_FIELD_MODE			0x00000020
+
+/* Field Sync Flip Enable */
+#define OVL_CMD_FIELD_SYNC_FLIP			0x00000080
+
+/* Buffer and Field */
+#define OVL_CMD_ACT_BUF0			0x00000000
+#define OVL_CMD_ACT_BUF1			0x00000004
+#define OVL_CMD_ACT_FLD0			0x00000000
+#define OVL_CMD_ACT_FLD1			0x00000002
+
+/* Initial phase register */
+#define Y_VPP_FLD0_PLUS1			0x100000
+#define Y_VPP_FLD0_PLUS2			0x200000
+#define Y_VPP_FLD0_MINUS1			0xF00000
+#define Y_VPP_FLD1_PLUS1			0x010000
+#define Y_VPP_FLD1_PLUS2			0x020000
+#define Y_VPP_FLD1_MINUS1			0x0F0000
+#define Y_HPP_PLUS1					0x001000
+#define Y_HPP_PLUS2					0x002000
+#define Y_HPP_MINUS1				0x00F000
+#define UV_VPP_FLD0_PLUS1			0x000100
+#define UV_VPP_FLD0_PLUS2			0x000200
+#define UV_VPP_FLD0_MINUS1			0x000F00
+#define UV_VPP_FLD1_PLUS1			0x000010
+#define UV_VPP_FLD1_PLUS2			0x000020
+#define UV_VPP_FLD1_MINUS1			0x0000F0
+#define UV_HPP_PLUS1				0x000001
+#define UV_HPP_PLUS2				0x000002
+#define UV_HPP_MINUS1				0x00000F
+
+#define OVL_REG_ADDR_GAMMA5						0x30010
+#define OVL_REG_ADDR_GAMMA4						0x30014
+#define OVL_REG_ADDR_GAMMA3						0x30018
+#define OVL_REG_ADDR_GAMMA2						0x3001C
+#define OVL_REG_ADDR_GAMMA1						0x30020
+#define OVL_REG_ADDR_GAMMA0						0x30024
+#define OVL_TOTAL_GAMMA_REG						6
+
+/* following value are needed because hardware seems to display yuv slightly dimmer
+   than RGB when color data is calculated out to be equal */
+#define MID_CONTRAST_YUV					0x43//4a
+#define MID_SATURATION_YUV					0x91//92
+#define MID_BRIGHTNESS_YUV					-5
+
+#endif /* OVL_REGISTER_IMAGE_H_ */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/micro_ovl_tnc.c b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/micro_ovl_tnc.c
new file mode 100644
index 0000000..1bcbf29
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/micro_ovl_tnc.c
@@ -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/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_regs_tnc.h b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_regs_tnc.h
new file mode 100644
index 0000000..9f2ac10
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_regs_tnc.h
@@ -0,0 +1,76 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl2_regs_tnc.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the internal header file for napa overlay engine. It should be not be
+ *  by any other module besides the overlay module itself. It contains the
+ *  neccessary hardware virtualized structures and functions internal to
+ *  the napa core's overlay engine
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _OVL2_REGS_TNC_H
+#define _OVL2_REGS_TNC_H
+/* Second Overlay Structure.
+ * These registers are the trigger registers and should be written
+ * last. */
+typedef struct _ovl2_reg_tnc{
+	unsigned int control;
+	unsigned int start;
+} ovl2_reg_tnc_t;
+
+/* Color Correction */
+#define OVL2_RGB_COLOR_DEF_CONT_BRGHT    0x1000000
+#define OVL2_RGB_COLOR_DEF_SATN_HUE      0x0000080
+
+/* Overlay Command Definitions */
+/* 422 Swap */
+#define OVL2_CMD_YVYU				0x00020000
+#define OVL2_CMD_UYVY				0x00010000
+#define OVL2_CMD_VYUY				0x00030000
+
+/* Source Format */
+#define OVL2_CMD_ARGB_8888			0x1C000000
+#define OVL2_CMD_RGB_8888			0x18000000
+#define OVL2_CMD_RGB_565			0x14000000
+#define OVL2_CMD_RGB_555			0x10000000
+#define OVL2_CMD_RGB_8				0x08000000
+#define OVL2_CMD_YUV_422			0x00000000 /*packed YUV422*/
+#define OVL2_CMD_SRC_FMT_MASK		0x3C000000 /*mask for above*/
+
+#define OVL2_REG_ADDR_GAMMA5						0x721E0
+#define OVL2_REG_ADDR_GAMMA4						0x721E4
+#define OVL2_REG_ADDR_GAMMA3						0x721E8
+#define OVL2_REG_ADDR_GAMMA2						0x721EC
+#define OVL2_REG_ADDR_GAMMA1						0x721F0
+#define OVL2_REG_ADDR_GAMMA0						0x721F4
+#define OVL2_TOTAL_GAMMA_REG						6
+
+/* following value are needed because hardware seems to display yuv slightly dimmer
+   than RGB when color data is calculated out to be equal */
+#define MID_CONTRAST_YUV					0x43//4a
+#define MID_SATURATION_YUV					0x91//92
+#define MID_BRIGHTNESS_YUV					-5
+#endif /* _OVL2_REGS_NAP_H */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.c b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.c
new file mode 100644
index 0000000..1c577c4
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.c
@@ -0,0 +1,460 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl2_tnc.c
+ * $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:
+ *  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;
+	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;
+	if(md && md->set_flip_pending){
+		OS_PTHREAD_MUTEX_LOCK(&platform->flip_mutex);
+		md->set_flip_pending(MMIO(display), 0x71024);
+		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;
+
+	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;
+		if(md && md->check_flip_pending){
+			ret = OS_PTHREAD_MUTEX_LOCK(&platform->flip_mutex);
+			if(md->check_flip_pending(MMIO(display), 0x71024)){
+				OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex);
+				EMGD_DEBUG("Overlay2 Sync done but Flip not done");
+				return FALSE;
+			}
+			OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex);
+		}
+
+		/* Now that we know the last flip is done and the register update is
+		 * complete, set the sync to 0 and return TRUE (Flip done). */
+		ovl_context->sync2 = FLIP_DONE;
+		break;
+	case IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE:
+		/* Wait for 200 milliseconds for the last flip to complete.  If not
+		 * done in that time, there is likely a hardware problem so return
+		 * FALSE. */
+		timeout = OS_SET_ALARM(200);
+		do {
+			if (TRUE ==
+				query_ovl2_tnc(display_h, IGD_OVL_QUERY_IS_LAST_FLIP_DONE)) {
+				EMGD_TRACE_EXIT;
+				return TRUE;
+			}
+		} while (!OS_TEST_ALARM(timeout));
+		EMGD_ERROR_EXIT("Timeout waiting for last flip done");
+		return FALSE;
+		break;
+	case IGD_OVL_QUERY_IS_GAMMA_SUPPORTED:
+		return TRUE;
+		break;
+	case IGD_OVL_QUERY_IS_VIDEO_PARAM_SUPPORTED:
+		return TRUE;
+		break;
+	}
+
+	EMGD_TRACE_EXIT;
+	return TRUE;
+}
+
+
+
+int query_max_size_ovl2_tnc(
+	igd_display_h display_h,
+	unsigned long pf,
+	unsigned int *max_width,
+	unsigned int *max_height)
+{
+	EMGD_TRACE_ENTER;
+
+	/* FIXME: Should this be size of FB? */
+	*max_width = 2048;
+	*max_height = 2048;
+
+	EMGD_TRACE_EXIT;
+	return IGD_SUCCESS;
+}
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.h b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.h
new file mode 100644
index 0000000..300e826
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl2_tnc.h
@@ -0,0 +1,55 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl2_tnc.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the internal header file for napa overlay engine. It should be not be
+ *  by any other module besides the overlay module itself. It contains the
+ *  neccessary hardware virtualized structures and functions internal to
+ *  the napa core's overlay engine
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _OVL2_TNC_H
+#define _OVL2_TNC_H
+extern int blend2_surf_needed_tnc(igd_display_context_t *display,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	unsigned int         flags,
+	igd_surface_t       *blend_surf,
+	igd_rect_t          *blend_rect);
+extern int alter_ovl2_tnc(igd_display_context_t *display,
+	igd_surface_t       *src_surf,
+	igd_rect_t          *src_rect,
+	igd_rect_t          *dest_rect,
+	igd_ovl_info_t      *ovl_info,
+	unsigned int         flags);
+extern int query_ovl2_tnc(igd_display_h display_h,
+	unsigned int flags);
+extern int query_max_size_ovl2_tnc(igd_display_h display_h,
+	unsigned long pf,
+	unsigned int *max_width,
+	unsigned int *max_height);
+#endif /* _OVL2_NAP_H */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_regs_tnc.h b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_regs_tnc.h
new file mode 100644
index 0000000..06e85f7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_regs_tnc.h
@@ -0,0 +1,190 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_regs_tnc.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the internal header file for overlay. It should be not be
+ *  by any other module besides the overlay module itself. It contains the
+ *  neccessary hardware virtualized register dependant information including
+ *  values, structures and addresses specifically for the Napa core
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef OVL_REGS_TNC_H_
+#define OVL_REGS_TNC_H_
+
+/* Overlay Update Register Image Structure.*/
+typedef struct _ovl_reg_image_tnc{
+
+	volatile unsigned int			buffer0_yrgb_loff;
+	volatile unsigned int			buffer1_yrgb_loff;
+	volatile unsigned int			buffer0_u_loff;
+	volatile unsigned int			buffer0_v_loff;
+	volatile unsigned int			buffer1_u_loff;
+	volatile unsigned int			buffer1_v_loff;
+	volatile unsigned short			yrgb_stride;
+	volatile unsigned short			uv_stride;
+	volatile unsigned short			yrgb_vert_phase_field0;
+	volatile unsigned short			yrgb_vert_phase_field1;
+	volatile unsigned short			uv_vert_phase_field0;
+	volatile unsigned short			uv_vert_phase_field1;
+	volatile unsigned short			yrgb_hphase;
+	volatile unsigned short			uv_hphase;
+	volatile unsigned int			init_phase_shift;
+	volatile unsigned short			dest_pos_x_left;
+	volatile unsigned short			dest_pos_y_top;
+	volatile unsigned short			dest_width_x;
+	volatile unsigned short			dest_height_y;
+	volatile unsigned short			source_yrgb_width;
+	volatile unsigned short			source_uv_width;
+	volatile unsigned short			source_yrgb_width_swords;
+	volatile unsigned short			source_uv_width_swords;
+	volatile unsigned short			source_yrgb_height;
+	volatile unsigned short			source_uv_height;
+	volatile unsigned int			yrgb_scale;
+	volatile unsigned int			uv_scale;
+	volatile unsigned int			col_ctl_brt_con;
+	volatile unsigned int			col_ctl_sat_hue;
+	volatile unsigned int			dest_ckey_val;
+	volatile unsigned int			dest_ckey_mask;
+	volatile unsigned int			source_ckey_high;
+	volatile unsigned int			source_ckey_low;
+	volatile unsigned int			source_ckey_mask;
+	volatile unsigned int			config;
+	volatile unsigned int			command;
+	volatile unsigned int			reserved1;
+	volatile unsigned int			buffer0_yrgb_start;
+	volatile unsigned int			buffer1_yrgb_start;
+	volatile unsigned int			buffer0_u_start;
+	volatile unsigned int			buffer0_v_start;
+	volatile unsigned int			buffer1_u_start;
+	volatile unsigned int			buffer1_v_start;
+	volatile unsigned short			buffer0_yrgb_x_toff;
+	volatile unsigned short			buffer0_yrgb_y_toff;
+	volatile unsigned short			buffer1_yrgb_x_toff;
+	volatile unsigned short			buffer1_yrgb_y_toff;
+	volatile unsigned short			buffer0_u_x_toff;
+	volatile unsigned short			buffer0_u_y_toff;
+	volatile unsigned short			buffer0_v_x_toff;
+	volatile unsigned short			buffer0_v_y_toff;
+	volatile unsigned short			buffer1_u_x_toff;
+	volatile unsigned short			buffer1_u_y_toff;
+	volatile unsigned short			buffer1_v_x_toff;
+	volatile unsigned short			buffer1_v_y_toff;
+	volatile unsigned int			reserved11;
+	volatile unsigned int			vert_downscale;
+	volatile unsigned int			reserved12[86];
+	volatile unsigned short			y_vert_coeff_single[52]; /*offset 0x200 --> 3*17/2 + 1*/
+	volatile unsigned int			reserved13[38];
+	volatile unsigned short			y_horz_coeff_single[86]; /*offset 0x300 --> 5*17/2 + 1*/
+	volatile unsigned int			reserved14[85];
+	volatile unsigned short			uv_vert_coeff_single[52]; /*offset 0x500 --> 3*17/2 + 1*/
+	volatile unsigned int			reserved15[38];
+	volatile unsigned short			uv_horz_coeff_single[52]; /*offset 0x600 --> 3*17/2 + 1*/
+	volatile unsigned int			reserved16[38];
+
+} ovl_reg_image_tnc_t;
+
+/* Color Correction */
+#define OVL_YUV_COLOR_DEF_CONT_BRGHT    0x10c00fb
+#define OVL_YUV_COLOR_DEF_SATN_HUE      0x0000091
+#define OVL_RGB_COLOR_DEF_CONT_BRGHT    0x1000000
+#define OVL_RGB_COLOR_DEF_SATN_HUE      0x0000080
+
+
+/* Overlay Config */
+#define OVL_CONFIG_NO_LINE_BUFF     0xffffffff
+#define OVL_CONFIG_TWO_LINE_BUFF    0x00000000
+#define OVL_CONFIG_THREE_LINE_BUFF  0x00000001
+#define OVL_CONFIG_LINE_BUFF_MASK   0x00000001
+
+/* Overlay Command Definitions */
+/* 422 Swap */
+#define OVL_CMD_UV_SWAP				0x00004000
+#define OVL_CMD_Y_SWAP				0x00008000
+#define OVL_CMD_YUV_SWAP			0x0000C000
+
+/* Source Format */
+#define OVL_CMD_RGB_8888			0x00000400
+#define OVL_CMD_RGB_565				0x00000C00
+#define OVL_CMD_RGB_555				0x00000800
+#define OVL_CMD_YUV_NV12Alt			0x00001C00 /*planar NV12, Alternate?*/
+#define OVL_CMD_YUV_NV12			0x00002C00 /*planar NV12*/
+#define OVL_CMD_YUV_422				0x00002000 /*packed YUV422*/
+#define OVL_CMD_YUV_411				0x00002400 /*packed YUV411*/
+#define OVL_CMD_YUV_420P			0x00003000 /*planar YUV420*/
+#define OVL_CMD_YUV_422P			0x00003400 /*planar YUV422*/
+#define OVL_CMD_YUV_410P			0x00003800 /*planar YUV410*/
+#define OVL_CMD_YUV_444P			0x00003C00 /*planar YUV444*/
+#define OVL_CMD_SRC_FMT_MASK		0x00003C00 /*mask for above*/
+
+/* Flip Type */
+#define OVL_CMD_FRAME_MODE          0x00000000
+#define OVL_CMD_FIELD_MODE			0x00000020
+
+/* Field Sync Flip Enable */
+#define OVL_CMD_FIELD_SYNC_FLIP			0x00000080
+
+/* Buffer and Field */
+#define OVL_CMD_ACT_BUF0			0x00000000
+#define OVL_CMD_ACT_BUF1			0x00000004
+#define OVL_CMD_ACT_FLD0			0x00000000
+#define OVL_CMD_ACT_FLD1			0x00000002
+
+/* Initial phase register */
+#define Y_VPP_FLD0_PLUS1			0x100000
+#define Y_VPP_FLD0_PLUS2			0x200000
+#define Y_VPP_FLD0_MINUS1			0xF00000
+#define Y_VPP_FLD1_PLUS1			0x010000
+#define Y_VPP_FLD1_PLUS2			0x020000
+#define Y_VPP_FLD1_MINUS1			0x0F0000
+#define Y_HPP_PLUS1					0x001000
+#define Y_HPP_PLUS2					0x002000
+#define Y_HPP_MINUS1				0x00F000
+#define UV_VPP_FLD0_PLUS1			0x000100
+#define UV_VPP_FLD0_PLUS2			0x000200
+#define UV_VPP_FLD0_MINUS1			0x000F00
+#define UV_VPP_FLD1_PLUS1			0x000010
+#define UV_VPP_FLD1_PLUS2			0x000020
+#define UV_VPP_FLD1_MINUS1			0x0000F0
+#define UV_HPP_PLUS1				0x000001
+#define UV_HPP_PLUS2				0x000002
+#define UV_HPP_MINUS1				0x00000F
+
+#define OVL_REG_ADDR_GAMMA5						0x30010
+#define OVL_REG_ADDR_GAMMA4						0x30014
+#define OVL_REG_ADDR_GAMMA3						0x30018
+#define OVL_REG_ADDR_GAMMA2						0x3001C
+#define OVL_REG_ADDR_GAMMA1						0x30020
+#define OVL_REG_ADDR_GAMMA0						0x30024
+#define OVL_TOTAL_GAMMA_REG						6
+
+/* following value are needed because hardware seems to display yuv slightly dimmer
+   than RGB when color data is calculated out to be equal */
+#define MID_CONTRAST_YUV					0x43//4a
+#define MID_SATURATION_YUV					0x91//92
+#define MID_BRIGHTNESS_YUV					-5
+
+#endif /* OVL_REGISTER_IMAGE_H_ */
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc.c b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc.c
new file mode 100644
index 0000000..116489c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc.c
@@ -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/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc_cache.c b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc_cache.c
new file mode 100644
index 0000000..734e0d6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc_cache.c
@@ -0,0 +1,246 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: ovl_tnc_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_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;
+
+	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_TNC_UPDATE_FLAGS;
+
+		/* Invalidating the flags cache will cause the following
+		 * bits to be re-calculated.  Clear them in preparation for
+		 * re-calculation. */
+		ovl_cache->ovl_regs.command &= ~ (OVL_CMD_FRAME_MODE      |
+						 OVL_CMD_FIELD_MODE      |
+						 OVL_CMD_FIELD_SYNC_FLIP |
+						 OVL_CMD_ACT_FLD1        |
+						 OVL_CMD_ACT_FLD0        );
+	}
+
+	/* Do a comparison to source surface */
+	if (is_changed_surf(&ovl_cache->src_surf, src_surf)) {
+		cache_changed |= IGD_OVL_TNC_UPDATE_SURF;
+		copy_surf_tnc(src_surf, ovl_cache);
+
+		/* invalidating the source surface will cause the driver
+		 * to recalculate the following bits in command */
+		ovl_cache->ovl_regs.command &= ~( OVL_CMD_YUV_422  |
+						 OVL_CMD_YUV_420P |
+						 OVL_CMD_YUV_410P |
+						 OVL_CMD_YUV_NV12 |
+						 OVL_CMD_Y_SWAP   |
+						 OVL_CMD_UV_SWAP  |
+						 OVL_CMD_RGB_8888 |
+						 OVL_CMD_RGB_565  |
+						 OVL_CMD_RGB_555  );
+
+		/* Invalidating the source surface will cause the driver
+		 * to recalculate the following bits in config */
+		ovl_cache->ovl_regs.config &= ~ ( (1<<4)                    |
+					    OVL_CONFIG_LINE_BUFF_MASK );
+
+	}
+
+	/* Do a comparison to source rectangle */
+	if (is_changed_rect(&ovl_cache->src_rect, src_rect)) {
+		cache_changed |= IGD_OVL_TNC_UPDATE_SRC;
+		copy_src_rect_tnc(src_rect, ovl_cache);
+
+		/* invalidating the source rectangle will cause the driver
+		 * to recalculate the following bits in command */
+		ovl_cache->ovl_regs.command &= ~( OVL_CMD_YUV_422  |
+						 OVL_CMD_YUV_420P |
+						 OVL_CMD_YUV_410P |
+						 OVL_CMD_YUV_NV12 |
+						 OVL_CMD_Y_SWAP   |
+						 OVL_CMD_UV_SWAP  |
+						 OVL_CMD_RGB_8888 |
+						 OVL_CMD_RGB_565  |
+						 OVL_CMD_RGB_555  );
+
+		/* Invalidating the source rectangle will cause the driver
+		 * to recalculate the following bits in config */
+		ovl_cache->ovl_regs.config &= ~ ( (1<<4)                    |
+					    OVL_CONFIG_LINE_BUFF_MASK );
+
+
+	}
+
+	/* Has our destination rectangle changed? */
+	if (is_changed_rect(&ovl_cache->dest_rect, dest_rect)) {
+		cache_changed |= IGD_OVL_TNC_UPDATE_DEST;
+		copy_dest_rect_tnc(dest_rect, ovl_cache);
+	}
+
+	/* Do a comparison to overlay info color key */
+	if (is_changed_color_key(&ovl_cache->ovl_info, ovl_info)) {
+		cache_changed |= (IGD_OVL_TNC_UPDATE_INFO |
+				  IGD_OVL_TNC_UPDATE_COLORKEY);
+		copy_color_key_tnc(ovl_info, ovl_cache);
+	}
+
+	/* Do a comparison to overlay info video quality */
+	if (is_changed_vq(&ovl_cache->ovl_info, ovl_info)) {
+		cache_changed |= ( IGD_OVL_TNC_UPDATE_INFO |
+				   IGD_OVL_TNC_UPDATE_VQ);
+		copy_vq_tnc(ovl_info, ovl_cache);
+	}
+
+	/* Do a comparison to overlay info gamma */
+	if (is_changed_gamma(&ovl_cache->ovl_info, ovl_info)) {
+		cache_changed |= ( IGD_OVL_TNC_UPDATE_INFO |
+				   IGD_OVL_TNC_UPDATE_GAMMA);
+		copy_gamma_tnc(ovl_info, ovl_cache);
+	}
+
+	return cache_changed;
+}
+
diff --git a/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc_cache.h b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc_cache.h
new file mode 100644
index 0000000..0df413a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/overlay/tnc/ovl_tnc_cache.h
@@ -0,0 +1,162 @@
+/*
+ *----------------------------------------------------------------------------
+ * Filename: ovl_tnc_cache.h
+ * $Revision: 1.5 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the internal header file for overlay caching. It should be not be
+ *  by any other module besides the overlay module itself.
+ *-----------------------------------------------------------------------------
+ */
+#ifndef _OVL_TNC_CACHE_H
+#define _OVL_TNC_CACHE_H
+
+#include <rb.h>
+#include "ovl_regs_tnc.h"
+#include "ovl2_regs_tnc.h"
+
+/* Turns the overlay cache on and off. */
+#define OVL_TNC_CACHE_QUICK_SWAP
+
+
+/*
+ * In order to cache the overlay registers we need a structure
+ * that defines and wraps them.  We already have one for the primary
+ * display, called ovl_reg_image_tnc_t.
+ * Here we define a structure for the secondary display
+ */
+
+typedef struct _ovl2_reg_tnc_cache{
+	unsigned long control;
+	unsigned long start;
+	unsigned long plane_control;
+	unsigned long plane_start;
+	unsigned long linear_offset;
+	unsigned long tiled_offset;
+
+	unsigned long pitch;
+	unsigned long dest_rect_x1y1;
+	unsigned long dest_rect_w_h;
+	unsigned long cont_bright;
+	unsigned long satn_hue;
+	unsigned long gamma_regs[OVL2_TOTAL_GAMMA_REG];
+	unsigned long colorkey_hw;
+	unsigned long colorkey_mask;
+	unsigned long ckey_high;
+	unsigned long ckey_low;
+	unsigned long ckey_enable;
+} ovl2_reg_tnc_cache_t;
+
+#define MMIO_OFFSET_TNC2_CONTROL        0x72180
+#define MMIO_OFFSET_TNC2_LINEAR_OFF     0x72184
+#define MMIO_OFFSET_TNC2_PITCH          0x72188
+#define MMIO_OFFSET_TNC2_DEST_RECT_X1Y1 0x7218C
+#define MMIO_OFFSET_TNC2_DEST_RECT_W_H  0x72190
+#define MMIO_OFFSET_TNC2_CKEY_LOW       0x72194
+#define MMIO_OFFSET_TNC2_CKEY_ENABLE    0x72198
+#define MMIO_OFFSET_TNC2_SURF_ADDR      0x7219C
+#define MMIO_OFFSET_TNC2_CKEY_HIGH      0x721A0
+#define MMIO_OFFSET_TNC2_DSPC_TILE_OFF  0x721A4
+#define MMIO_OFFSET_TNC2_CONT_BRIGHT    0x721D0
+#define MMIO_OFFSET_TNC2_SATN_HUE       0x721D4
+#define MMIO_OFFSET_TNC2_COLORKEY_HW    0x14
+#define MMIO_OFFSET_TNC2_COLORKEY_MASK  0x18
+
+/*
+ * This stucture caches the overlay state, so we don't have to
+ * re-program everything for every single frame
+ */
+typedef struct _ovl_tnc_cache {
+	igd_surface_t        src_surf;
+	igd_rect_t           src_rect;
+	igd_rect_t           dest_rect;
+	igd_ovl_info_t       ovl_info;
+	unsigned long        flags;
+	ovl_reg_image_tnc_t  ovl_regs;
+	ovl2_reg_tnc_cache_t ovl2_regs;
+} ovl_tnc_cache_t, *povl_tnc_cache_t;
+
+
+/* Flags for things that might have changed in the cache */
+#define IGD_OVL_TNC_UPDATE_DEST     (1 << 0)
+#define IGD_OVL_TNC_UPDATE_SRC      (1 << 1)
+#define IGD_OVL_TNC_UPDATE_SURF     (1 << 2)
+#define IGD_OVL_TNC_UPDATE_INFO     (1 << 3)
+#define IGD_OVL_TNC_UPDATE_FLAGS    (1 << 4)
+#define IGD_OVL_TNC_UPDATE_VQ       (1 << 5)
+#define IGD_OVL_TNC_UPDATE_GAMMA    (1 << 6)
+#define IGD_OVL_TNC_UPDATE_COLORKEY (1 << 7)
+
+
+/*
+ * Caching helper functions.  Implemented in ovl_tnc.c, but used by
+ * the ovl2 and micro_ovl modules as well.
+ */
+
+/* Tells if a rectangle has changed */
+int is_changed_rect(igd_rect_t *old_rect, igd_rect_t *new_rect);
+
+/* Tells if a surface has changed */
+int is_changed_surf(igd_surface_t *old_surf, igd_surface_t *new_surf);
+
+/* Tells if the color key has changed */
+int is_changed_color_key(igd_ovl_info_t *old_info, igd_ovl_info_t *new_info);
+
+/* Tells if the video quality has changed */
+int is_changed_vq(igd_ovl_info_t *old_info, igd_ovl_info_t *new_info);
+
+/* Tells if the gamma has changed */
+int is_changed_gamma(igd_ovl_info_t *old_info, igd_ovl_info_t *new_info);
+
+/* Copies a source rectangle to the cache */
+void copy_src_rect_tnc(igd_rect_t *src_rect, povl_tnc_cache_t ovl_cache);
+
+/* Copies a dest rectangle to the cache */
+void copy_dest_rect_tnc( igd_rect_t *dest_rect, povl_tnc_cache_t ovl_cache);
+
+/* Copies a surface to the cache */
+void copy_surf_tnc(igd_surface_t *src_surf, povl_tnc_cache_t ovl_cache);
+
+/* Copies the color key to the cache */
+void copy_color_key_tnc( igd_ovl_info_t *ovl_info, povl_tnc_cache_t ovl_cache);
+
+/* Copies the video quality info to the cache */
+void copy_vq_tnc(igd_ovl_info_t *ovl_info, povl_tnc_cache_t ovl_cache);
+
+/* Copies the gamma to the cache */
+void copy_gamma_tnc(igd_ovl_info_t *ovl_info, povl_tnc_cache_t ovl_cache);
+
+/* Checks to see what, if anything has changed.
+ * Clears bits in the command and config register that are invalid.
+ * Returns a set of flags telling what changed */
+unsigned int get_cache_changes_tnc(
+	igd_surface_t  *src_surf,
+	igd_rect_t     *src_rect,
+	igd_rect_t     *dest_rect,
+	igd_ovl_info_t *ovl_info,
+	unsigned int    flags,
+	povl_tnc_cache_t ovl_cache);
+
+
+
+#endif /* _OVL_TNC_CACHE_H */
diff --git a/drivers/gpu/drm/emgd/emgd/video/topaz/topaz.c b/drivers/gpu/drm/emgd/emgd/video/topaz/topaz.c
new file mode 100644
index 0000000..f710ff2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/topaz/topaz.c
@@ -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/drivers/gpu/drm/emgd/emgd/video/topaz/topaz_hdr.h b/drivers/gpu/drm/emgd/emgd/video/topaz/topaz_hdr.h
new file mode 100644
index 0000000..3545684
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/topaz/topaz_hdr.h
@@ -0,0 +1,128 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: topaz_hdr.h
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef TOPAZ_HDR_H
+#define TOPAZ_HDR_H
+
+#define MTX_CCBCTRL_ROFF		0
+#define MTX_CCBCTRL_COMPLETE		4
+#define MTX_CCBCTRL_CCBSIZE		8
+#define MTX_CCBCTRL_QP			12
+#define MTX_CCBCTRL_FRAMESKIP		20
+#define MTX_CCBCTRL_INITQP		24
+
+#define TOPAZ_CTX(ctx) \
+	((platform_context_tnc_t *)(ctx)->platform_context)->tpz_private_data
+
+
+#define TOPAZ_BEGIN_CCB(ctx) \
+	write_mtx_mem_multiple_setup((ctx), \
+	TOPAZ_CTX((ctx)).topaz_ccb_buffer_addr + \
+	TOPAZ_CTX((ctx)).topaz_cmd_windex * 4)
+
+#define TOPAZ_OUT_CCB(ctx, cmd) \
+	write_mtx_mem_multiple((ctx), (cmd)); \
+	TOPAZ_CTX((ctx)).topaz_cmd_windex++;
+
+#define TOPAZ_END_CCB(ctx, kick_cnt) \
+	EMGD_WRITE32(1,  (ctx)->device_context.virt_mmadr + TNC_TOPAZ_MTX_KICK);
+
+/* macros to get/set CCB control data */
+#define WB_CCB_CTRL_RINDEX(ctx) \
+*((unsigned long *)TOPAZ_CTX(ctx).topaz_ccb_wb)
+
+#define WB_CCB_CTRL_SEQ(ctx) \
+*((unsigned long *)(TOPAZ_CTX(ctx).topaz_ccb_wb + 1))
+
+/* HACK: temporary turn off MMU bypass to POLL, then turn on
+#define POLL_WB_RINDEX(ctx, value)				\
+do {								\
+	int i;							\
+	unsigned char *mmio = ctx->device_context.virt_mmadr;   \
+	EMGD_WRITE32(0x00000000, mmio + TNC_TOPAZ_MMU_CONTROL0);\
+	for (i = 0; i < 10000; i++) {				\
+		if (CCB_CTRL_RINDEX(ctx) == value)	\
+			break;					\
+		else						\
+			OS_SLEEP(100);			\
+	}							\
+	if (CCB_CTRL_RINDEX(ctx) != value) {		\
+		EMGD_ERROR("TOPAZ: poll rindex timeout\n");	\
+		ret = -IGD_ERROR_HWERROR;					\
+	}							\
+	EMGD_WRITE32(0x00000800, mmio + TNC_TOPAZ_MMU_CONTROL0);\
+} while (0)*/
+
+#define POLL_WB_RINDEX(ctx, value)				\
+do {								\
+	int i;							\
+	for (i = 0; i < 10000; i++) {				\
+		if (CCB_CTRL_RINDEX(ctx) == value)	\
+			break;					\
+		else						\
+			OS_SLEEP(100);			\
+	}							\
+	if (CCB_CTRL_RINDEX(ctx) != value) {		\
+		EMGD_ERROR("TOPAZ: poll rindex timeout\n");	\
+		ret = -IGD_ERROR_HWERROR;					\
+	}							\
+} while (0)
+
+#define CCB_CTRL_RINDEX(ctx)			\
+	read_mtx_mem(ctx, 			\
+	TOPAZ_CTX(ctx).topaz_ccb_ctrl_addr + MTX_CCBCTRL_ROFF)
+
+#define CCB_CTRL_SET_QP(ctx, qp)				\
+	write_mtx_mem(ctx,					\
+		TOPAZ_CTX(ctx).topaz_ccb_ctrl_addr + MTX_CCBCTRL_QP, qp)
+
+#define CCB_CTRL_FRAMESKIP(ctx)				   \
+	read_mtx_mem(ctx,				   \
+	    TOPAZ_CTX(ctx).topaz_ccb_ctrl_addr + MTX_CCBCTRL_FRAMESKIP)
+
+#define CCB_CTRL_SEQ(ctx)				\
+	read_mtx_mem(ctx,				\
+	    TOPAZ_CTX(ctx).topaz_ccb_ctrl_addr + MTX_CCBCTRL_COMPLETE)
+
+
+void write_mtx_mem_multiple_setup(igd_context_t *context,
+		unsigned long addr);
+
+void write_mtx_mem_multiple(igd_context_t *context,
+		unsigned long cmd);
+
+unsigned long read_mtx_mem(igd_context_t *, unsigned long );
+
+void write_mtx_mem(igd_context_t *,
+		unsigned long ,
+		unsigned long );
+
+#endif /* TOPAZ_HDR_H */
diff --git a/drivers/gpu/drm/emgd/emgd/video/topaz/topaz_init.c b/drivers/gpu/drm/emgd/emgd/video/topaz/topaz_init.c
new file mode 100644
index 0000000..4401b69
--- /dev/null
+++ b/drivers/gpu/drm/emgd/emgd/video/topaz/topaz_init.c
@@ -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/drivers/gpu/drm/emgd/include/emgd_drm.h b/drivers/gpu/drm/emgd/include/emgd_drm.h
new file mode 100644
index 0000000..c2b871a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/emgd_drm.h
@@ -0,0 +1,916 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_drm.h
+ * $Revision: 1.63 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF 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 <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;
+	};
+} 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
+
+/*
+ * 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/drivers/gpu/drm/emgd/include/emgd_shared.h b/drivers/gpu/drm/emgd/include/emgd_shared.h
new file mode 100644
index 0000000..fe576ed
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/emgd_shared.h
@@ -0,0 +1,98 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: emgd_shared.h
+ * $Revision: 1.14 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This include file contains information that is shared between the various
+ *  EMGD driver components.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _EMGD_SHARED_H
+#define _EMGD_SHARED_H
+
+/*
+ * Module name is the name of the drm kernel module. This is used by
+ * user space components to open a connection to the module. A typical
+ * call would look like  -- drmOpen(EMGD_MODULE_NAME, NULL);
+ */
+#define EMGD_MODULE_NAME "emgd"
+
+#define EMGD_DRIVER_NAME "emgd"
+
+/*
+ * EMGD-specific numbering of the PVR DRM ioctls.  The EMGD DRM module is in
+ * charge, and includes the PVR DRM code.  As such, the PVR ioctls are included
+ * in with the EMGD ioctls ("emgd_drm.h"), and must be kept in sync.  Both sets
+ * of these ioctls are mapped to the device specific range between 0x40 and
+ * 0x79.
+ *
+ * Client driver must use these values!
+ */
+#define DRM_PVR_RESERVED1	0x12
+#define DRM_PVR_RESERVED2	0x13
+#define DRM_PVR_RESERVED3	0x14
+#define DRM_PVR_RESERVED4	0x15
+#define DRM_PVR_RESERVED5	0x16
+#define DRM_PVR_RESERVED6	0x1E
+
+
+/*
+ * The following typedefs support the ability of non-HAL software to have a
+ * function called when a VBlank interrupt occurs.
+ */
+
+/**
+ * A pointer to a non-HAL-provided function that processes a VBlank interrupt.
+ */
+typedef int (*emgd_process_vblank_interrupt_t)(void *priv);
+
+/**
+ * This structure allows the HAL to track a non-HAL callback (and its
+ *  parameter) to call when a VBlank interrupt occurs for a given port.  An
+ *  opaque pointer to this structure serves as a unique identifier for the
+ *  callback/port combination.
+ */
+typedef struct _emgd_vblank_callback {
+	/** Non-HAL callback function to process a VBlank interrupt. */
+	emgd_process_vblank_interrupt_t callback;
+	/** An opaque pointer to a non-HAL data structure (passed to callback). */
+	void *priv;
+	/** Which HAL port number is associated with this interrupt callback. */
+	unsigned long port_number;
+} emgd_vblank_callback_t;
+
+/**
+ * An opaque pointer to a emgd_vblank_callback_t.  This pointer serves as a
+ * unique identifier for the callback/port combination.
+ */
+typedef void *emgd_vblank_callback_h;
+
+/**
+ * A special value of a emgd_vblank_callback_h, meaning ALL devices/displays.
+ */
+#define ALL_PORT_CALLBACKS	((void *) 1001)
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/gart.h b/drivers/gpu/drm/emgd/include/gart.h
new file mode 100644
index 0000000..228ac41
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/gart.h
@@ -0,0 +1,38 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: gart.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains OS independent abstractions for common gart
+ *  operations.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OAL_GART_H
+#define _OAL_GART_H
+
+typedef void * os_gart_allocation_t;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/igd.h b/drivers/gpu/drm/emgd/include/igd.h
new file mode 100644
index 0000000..f153eaf
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd.h
@@ -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/drivers/gpu/drm/emgd/include/igd_2d.h b/drivers/gpu/drm/emgd/include/igd_2d.h
new file mode 100644
index 0000000..f7ee253
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_2d.h
@@ -0,0 +1,380 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_2d.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is a header file for the Intel GFX commands.
+ *  This includes commands specific to Intel hardware and structures specific
+ *  to Intel hardware.  All other commands and structures are available
+ *  through GFX.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_2D_H
+#define _IGD_2D_H
+
+/* Needed for igd_display_h and pixel_format. */
+#include <igd_mode.h>
+#include <igd_render.h>
+#include <igd_appcontext.h>
+
+/* byte mask */
+#define IGD_ALPHA_CHANNEL 0x200000
+#define IGD_RGB_CHANNEL   0x100000
+
+/* flags for XY_SETUP_CLIP_BLT */
+#define IGD_CLIP_ENABLED		0x01
+#define IGD_CLIP_DISABLED		0x00
+
+/* flags for igd_mono_src_t->pat_select_transp_mode for functions
+ *  igd_mono_src_copy_blt
+ *  igd_full_mono_src_blt
+ *  igd_full_mono_pat_blt
+ *  igd_full_mono_pat_mono_src_blt
+ */
+#define IGD_SRC_TRANSP_MODE_BACKGROUND	(0x0 << 29)
+#define IGD_SRC_TRANSP_MODE_ENABLED		(0x1 << 29)
+
+/* flags for igd_mono_pat_t->pat_select_transp_mode for functions
+ *  igd_full_mono_pat_blt
+ *  igd_full_mono_pat_mono_src_blt
+*/
+#define IGD_PAT_SOLID                   (0x1 << 31)
+#define IGD_PAT_NO_SOLID                (0x0 << 31)
+
+/* flags for igd_mono_pat_t->pat_select_transp_mode for functions
+ *  igd_mono_pat_blt
+ *  igd_full_mono_pat_blt
+ *  igd_full_mono_pat_mono_src_blt
+ * FIXME: Does this work for igd_full_mono_pat_blt???
+ */
+#define IGD_PAT_TRANSP_MODE_BACKGROUND	(0x0 << 28)
+#define IGD_PAT_TRANSP_MODE_ENABLED		(0x1 << 28)
+
+
+/* chroma transparency range mode */
+#define IGD_NO_TRANSP             0
+#define IGD_SRC_RGB_TRANSP        1
+#define IGD_SRC_RGB_ALPHA_TRANSP  2
+#define IGD_DEST_RGB_TRANSP       3
+#define IGD_DEST_RGB_ALPHA_TRANSP 4
+
+
+typedef struct igd_chroma {
+	unsigned int transp_range_mode;
+	unsigned int color_low;
+	unsigned int color_high;
+} igd_chroma_t;
+
+typedef struct igd_mono_src {
+	unsigned int data_bit_pos;
+	unsigned int mono_src_transp_mode;
+	/*
+	 * FIXME: Maybe. Immediate mode instructions need a virtual
+	 *  address. The rest need an offset. Hence there are two
+	 *  address values in this structure. The type of instructure
+	 *  determines which one is used.  This is a bit confusing for
+	 *  the IAL layer. Ideally, these would be combined into one value.
+	 */
+	unsigned long addr;
+	unsigned char *virt_addr;  /* Used by Immediate mode instructions */
+	unsigned int bgcolor;
+	unsigned int fgcolor;
+	int mono_src_size;
+} igd_mono_src_t;
+
+/* fixed pattern not supported yet */
+typedef struct igd_mono_pat {
+	unsigned int pat_select_transp_mode;
+	unsigned int horiz_seed;
+	unsigned int vert_seed;
+	unsigned int bgcolor;
+	unsigned int fgcolor;
+	unsigned int data0;
+	unsigned int data1;
+} igd_mono_pat_t;
+
+typedef struct igd_pat {
+	unsigned int horiz_seed;
+	unsigned int vert_seed;
+	unsigned long base_addr;
+    unsigned char *virt_addr;
+} igd_pat_t;
+
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  int dispatch->setup_clip_blt(igd_display_h display_handle,
+ *    int priority,
+ *    igd_rect_t *dest_rect,
+ *    igd_appcontext_h appcontext_handle,
+ *    unsigned int flags);
+ *
+ * Description:
+ *  XY_SETUP_CLIP_BLT: used to change the clip coordinate registers
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  int dispatch->color_blt(igd_display_h display_handle,
+ *    int priority,
+ *    igd_surface_t *dest,
+ *    igd_rect_t *dest_rect,
+ *    unsigned int byte_mask,
+ *    unsigned int color,
+ *    unsigned int raster_ops,
+ *    igd_appcontext_h appcontext,
+ *    unsigned int flags);
+ *
+ * Description:
+ *  color_blt: copy solid_color to dest at specific address
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  int dispatch->rgb_color_blt(igd_display_h display_handle,
+ *    int priority,
+ *    igd_surface_t *dest,
+ *    igd_rect_t *dest_rect,
+ *    unsigned int byte_mask,
+ *    unsigned int color,
+ *    unsigned int raster_ops,
+ *    igd_appcontext_h appcontext,
+ *    unsigned int flags);
+ *
+ * Description:
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  int dispatch->pat_blt(igd_display_h display_handle,
+ *    int priority,
+ *    igd_surface_t *dest,
+ *    igd_rect_t *dest_rect,
+ *    unsigned int byte_mask,
+ *    igd_pat_t *pat,
+ *    igd_chroma_t *chroma,
+ *    unsigned int raster_ops,
+ *    igd_appcontext_h appcontext,
+ *    unsigned int flags);
+ *
+ * Description:
+ *  pat_blt() copy a color pattern to the dest surface
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  int dispatch->mono_pat_blt(igd_display_h display_handle,
+ *    int priority,
+ *    igd_surface_t *dest,
+ *    igd_rect_t *dest_rect,
+ *    unsigned int byte_mask,
+ *    igd_mono_pat_t *pat,
+ *    unsigned int raster_ops,
+ *    igd_appcontext_h appcontext,
+ *    unsigned int flags);
+ *
+ * Description:
+ *  mono_pat_blt(): copy a monochrome pattern to the dest surface
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  int dispatch->src_copy_blt(igd_display_h display_handle,
+ *    int priority,
+ *    igd_surface_t *dest,
+ *    igd_rect_t *dest_rect,
+ *    igd_surface_t *src,
+ *    igd_coord_t *src_coord,
+ *    unsigned int byte_mask,
+ *    igd_chroma_t *chroma,
+ *    unsigned int raster_ops,
+ *    igd_appcontext_h appcontext,
+ *    unsigned int flags);
+ *
+ * Description:
+ *  src_copy_blt: copy a source surface to the dest surface
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  int dispatch->mono_src_copy_blt(igd_display_h display_handle,
+ *    int priority,
+ *    igd_surface_t *dest,
+ *    igd_rect_t *dest_rect,
+ *    igd_mono_src_t *src,
+ *    unsigned int byte_mask,
+ *    unsigned int raster_ops,
+ *    igd_appcontext_h appcontext,
+ *    unsigned int flags);
+ *
+ * Description:
+ *  mono_src_copy_blt: color source copy with chroma-keying
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  int dispatch->full_blt(igd_display_h display_handle,
+ *    int priority,
+ *    igd_surface_t *dest,
+ *    igd_rect_t *dest_rect,
+ *    igd_surface_t *src,
+ *    igd_coord_t *src_coord,
+ *    unsigned int byte_mask,
+ *    igd_pat_t *pat,
+ *    unsigned int raster_ops,
+ *    igd_appcontext_h appcontext,
+ *    unsigned int flags);
+ *
+ * Description:
+ *  full_blt: copy with specification of destination, source
+ *  and pattern
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  int dispatch->full_mono_src_blt(igd_display_h display_handle,
+ *    int priority,
+ *    igd_surface_t *dest,
+ *    igd_rect_t *dest_rect,
+ *    igd_mono_src_t *src,
+ *    unsigned int byte_mask,
+ *    igd_pat_t *pat,
+ *    unsigned int raster_ops,
+ *    igd_appcontext_h appcontext,
+ *    unsigned int flags);
+ *
+ * Description:
+ *  full_mono_src_blt: copy with specification of destination, source
+ *  and pattern where source is monochrome
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ *   int dispatch->full_mono_pat_blt(igd_display_h display_handle,
+ *     int priority,
+ *     igd_surface_t *dest,
+ *     igd_rect_t *dest_rect,
+ *     igd_coord_t *src_coord,
+ *     igd_surface_t *src,
+ *     unsigned int byte_mask,
+ *     igd_mono_pat_t *pat,
+ *     unsigned int raster_ops,
+ *     igd_appcontext_h appcontext,
+ *     unsigned int flags);
+ *
+ * Description:
+ *  full_mono_pat_blt copy with specification of destination, source
+ *  and pattern where pattern is monochrome
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  int dispatch->full_mono_pat_mono_src_blt(igd_display_h display_handle,
+ *    int priority,
+ *    igd_surface_t *dest,
+ *    igd_rect_t *dest_rect,
+ *    igd_mono_src_t *src,
+ *    unsigned int byte_mask,
+ *    igd_mono_pat_t *pat,
+ *    unsigned int raster_ops,
+ *    igd_appcontext_h appcontext,
+ *    unsigned int flags);
+ *
+ * Description:
+ *  full_mono_pat_mono_src_blt copy with specification of destination, source
+ *  and pattern where patter and source are monochrome
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+#endif /* _IGD_2D_H */
diff --git a/drivers/gpu/drm/emgd/include/igd_appcontext.h b/drivers/gpu/drm/emgd/include/igd_appcontext.h
new file mode 100644
index 0000000..d987937
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_appcontext.h
@@ -0,0 +1,72 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_appcontext.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is an IGD exported header file for the client context Module.
+ *  This module includes tools for maintaining device state including
+ *  hardware context allocation.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_APPCONTEXT_H
+#define _IGD_APPCONTEXT_H
+
+typedef void *igd_appcontext_h;
+
+#define IGD_CONTEXT_STATE_2D     0x00000001
+#define IGD_CONTEXT_STATE_3D     0x00000002
+#define IGD_CONTEXT_STATE_VD     0x00000004
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  igd_appcontext_h dispatch->appcontext_alloc(igd_display_h display_handle,
+ *    int priority,
+ *    unsigned int flags);
+ *
+ * Description:
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  void dispatch->appcontext_free(igd_display_h display_handle,
+ *    int priority,
+ *    igd_appcontext_h context_handle);
+ *
+ * Description:
+ *
+ * Parameters:
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/igd_blend.h b/drivers/gpu/drm/emgd/include/igd_blend.h
new file mode 100644
index 0000000..2ea3eb6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_blend.h
@@ -0,0 +1,73 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_blend.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is a header file for the Intel GFX commands.
+ *  This includes commands specific to Intel hardware and structures specific
+ *  to Intel hardware.  All other commands and structures are available
+ *  through GFX.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_BLEND_H
+#define _IGD_BLEND_H
+
+#include <igd_render.h>
+
+/* These flags must not conflict with the IGD_RENDER flags in igd_render.h */
+#define IGD_FILTER_MASK             0x00000300
+#define IGD_FILTER_NEAREST          0x00000000
+#define IGD_FILTER_BILINEAR         0x00000100
+#define IGD_FILTER_ANISOTROPIC      0x00000200
+#define IGD_FILTER_4X4              0x00000300
+/* Indicates multiple blends will be sent in a row and this is not the
+ * last blend. */
+#define IGD_BLEND_NO_FLUSH          0x00000800
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  int dispatch->blend(igd_display_h display_handle,
+ *    int priority,
+ *    igd_appcontext_h appcontext,
+ *    unsigned int num_src,
+ *    igd_surface_t **src_surface_list,
+ *    igd_rect_t **src_rect_list,
+ *    igd_rect_t **dest_rect_list,
+ *    igd_surface_t *dest_surface,
+ *    igd_rect_t *clip_rect,
+ *    unsigned long flags);
+ *
+ * Description:
+ *
+ * Parameters:
+ *
+ *  flags: Flags are defined in igd_render.h
+ *
+ * Returns:
+ *----------------------------------------------------------------------
+ */
+
+#endif /* _IGD_BLEND_H */
diff --git a/drivers/gpu/drm/emgd/include/igd_debug.h b/drivers/gpu/drm/emgd/include/igd_debug.h
new file mode 100644
index 0000000..455b182
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_debug.h
@@ -0,0 +1,72 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_debug.h
+ * $Revision: 1.10 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains data structures and variables needed to control
+ *  debugging within the IEGD driver.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_DEBUG_H
+#define _IGD_DEBUG_H
+
+typedef struct _igd_debug {
+	struct {
+		/* Per-Module Debug Bits */
+		short cmd      ;
+		short dsp      ;
+		short mode     ;
+		short init     ;
+		short overlay  ;
+		short power    ;
+		short _2d      ;
+		short blend    ;
+		short state    ;
+		short gmm      ;
+		short gart     ;
+		short oal      ;
+		short intr     ;
+		short dpd      ;
+		short video    ;
+		short pvr3dd   ;
+		short buf_class;
+		/* Global Debug Bits */
+		short trace    ;
+		short instr    ;
+		short debug    ;
+		/* Verbose debug bits */
+		short blend_stats        ;
+		short dump_overlay_regs  ;
+		short dump_command_queue ;
+		short dump_gmm_on_fail   ;
+		short dump_shaders       ;
+	} hal;
+} igd_debug_t;
+
+extern igd_debug_t *emgd_debug;
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/igd_errno.h b/drivers/gpu/drm/emgd/include/igd_errno.h
new file mode 100644
index 0000000..ee0c69c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_errno.h
@@ -0,0 +1,60 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_errno.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains igd error definitions.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_ERRNO_H
+#define _IGD_ERRNO_H
+
+/* Error values, must be <64kb for vBIOS */
+#define IGD_ERROR_NOMEM           0x0001
+#define IGD_ERROR_INVAL           0x0002
+#define IGD_ERROR_BUSY            0x0003
+#define IGD_ERROR_PWRDOWN         0x0004
+#define IGD_ERROR_NODEV           0x0005
+#define IGD_ERROR_HWERROR         0x0006
+#define IGD_ERROR_EDID            0x0007
+#define IGD_ERROR_INVAL_CONTEXT   0x0008
+#define IGD_ERROR_INVAL_PARAM     0x0009
+#define IGD_ERROR_IOCTL           0x000A
+#define IGD_ERROR_GENERIC         0x000B
+#define IGD_ERROR_BLT_NOTCOMPLETE 0x000B
+#define IGD_ERROR_NOT_IMPLEMENTED 0x000C
+#define IGD_ERROR_MAPPING_FAILED  0x000D
+
+#define IGD_NO_MEM           IGD_ERROR_NOMEM
+#define IGD_INVAL            IGD_ERROR_INVAL
+
+/* Success value */
+#define IGD_SUCCESS               0
+#define IGD_SUCCESS_DO_QRY_SETMODE    0x1001
+
+#define IGD_DO_QRY_SETMODE        IGD_SUCCESS_DO_QRY_SETMODE
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/igd_gart.h b/drivers/gpu/drm/emgd/include/igd_gart.h
new file mode 100644
index 0000000..568e271f9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_gart.h
@@ -0,0 +1,77 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_gart.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_GART_H_
+#define _IGD_GATR_H_
+
+typedef struct _gtt_info {
+	void* virt_mmadr;
+	void* virt_gttadr;
+	void* virt_gttadr_upper;
+
+	unsigned long new_gtt;
+	unsigned long gtt_phyadr;
+	unsigned long is_virt_aperture;
+	unsigned long reset_gtt_entries;
+	unsigned long fb_phys_addr;
+	unsigned long scratch_phys;
+
+	unsigned long num_gtt_entries;
+	unsigned long gtt_entry_start;
+	unsigned long gtt_entry_end;
+	unsigned long num_contig_allocs;
+	unsigned char **cont_pages_virts;
+	/* FIXME!!! - this cant handle 64-bit Architecture*/
+	unsigned long *cont_pages_phys;
+	unsigned long *cont_pages_sizes;
+#ifdef D3D_DPM_ALLOC
+   void* virt_gttadr_dpm;
+#endif
+}gtt_info_t;
+
+/*
+ * Note: Platforms extend this data structure so the pointer can be used
+ * as either this DI dispatch or cast to the DD dipatch.
+ */
+typedef struct _init_gart_dispatch {
+	int (*get_gtt_ctl)(void* gtt_info);
+	int (*init_gtt_table)(void* gtt_info);
+	int (*flush_gtt_tlb)(void* gtt_info);
+	int (*shutdown_gtt)(void* gtt_info);
+} init_gart_dispatch_t;
+
+void* igd_get_gtt_dispatch(unsigned long dev_id);
+int igd_get_gtt_ctl(void* gtt_info, unsigned long dev_id);
+int igd_init_gtt(void* gtt_info, unsigned long dev_id);
+int igd_flush_gtt(void* gtt_info, unsigned long dev_id);
+int igd_shutdown_gtt(void* gtt_info, unsigned long dev_id);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/igd_gmm.h b/drivers/gpu/drm/emgd/include/igd_gmm.h
new file mode 100644
index 0000000..e28a809
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_gmm.h
@@ -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/drivers/gpu/drm/emgd/include/igd_init.h b/drivers/gpu/drm/emgd/include/igd_init.h
new file mode 100644
index 0000000..47045b6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_init.h
@@ -0,0 +1,895 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_init.h
+ * $Revision: 1.15 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_INIT_H_
+#define _IGD_INIT_H_
+
+#include <igd.h>
+
+
+/*!
+ * @addtogroup init_group
+ *
+ * The init module contains the entry points and data structures
+ * necessary to initialize the graphics driver HAL.
+ * The IAL will call several initialization functions to bring the HAL
+ * to a usable state, after which, the HAL is accessed through a dispatch
+ * table (data structure of function pointers).
+ *
+ * Typical initialization will follow these steps:
+ * - Initialize the HAL by calling igd_driver_init() to
+ *   detect supported chipsets without altering the hardware. If a
+ *   supported device is found the _igd_init_info data structure will be
+ *   populated indicating the chipset name and PCI information for the device.
+ *   A driver handle that should be used during the rest of the
+ *   initialization process will be returned.
+ *
+ * - Call igd_driver_config() to prepare the hardware for use. Until this
+ *   point there has been no alteration of the hardware. After the
+ *   driver has been configured the igd_get_config_info() function can
+ *   be used. Only a subset of the _igd_config_info data will be available
+ *   at this time as the modular HAL components have not been initialized.
+ *
+ * - Call igd_module_init() to initialize the modular components of the
+ *   driver. This function accepts a set of parameters that can alter
+ *   default behavior. A provided dispatch table will be populated with
+ *   the entry points used for hardware operations during the life of
+ *   the driver. igd_get_config_info() may now be used to return full
+ *   configuration details.
+ *
+ * @{
+ */
+
+/*!
+ * @brief Data populated by igd_driver_init().
+ *
+ * The init info is used as input/output to igd_driver_init(). Any non-zero
+ * members (with the exception of the name) will be used to limit the search
+ * for available devices, if all members are zero the first supported
+ * device found on the system will be used. In either case the data returned
+ * will reflect the to-be-controlled device found by the HAL.
+ *
+ * The name is a ASCII string that may be used in human readable output
+ * dialogs.
+ */
+typedef struct _igd_init_info {
+	/*! @brief PCI Vendor ID */
+	unsigned int vendor_id;
+	/*! @brief PCI Device ID */
+	unsigned int device_id;
+	/*! @brief PCI Bus ID */
+	unsigned int bus;
+	/*! @brief PCI Slot ID */
+	unsigned int slot;
+	/*! @brief PCI Function ID */
+	unsigned int func;
+	/*! @brief ASCII chipset name */
+	char *name;
+	/*! @brief ASCII chipset ID */
+	char *chipset;
+	/*! @brief ASCII default port driver list */
+	char *default_pd_list;
+} igd_init_info_t;
+
+/*!
+ * @brief Function to initialize the HAL and detect supported chipset.
+ *
+ * Initialize the driver and determine if the hardware is supported without
+ * altering the hardware state in any way. Init info is populated based on
+ * collected data.
+ *
+ * A driver handle is returned. This handle is an opaque data structure
+ * used with future HAL calls. The contents or meaning of the value are
+ * not known outside the HAL; however, a NULL value should be considered
+ * a failure.
+ *
+ * @param init_info Device details returned from the init process. This
+ *   structure will be populated by the HAL during the call.
+ *
+ * @return igd_driver_h (Non-NULL) on Success
+ * @return NULL on failure
+ */
+igd_driver_h igd_driver_init(igd_init_info_t *init_info);
+
+
+/*!
+ *  Configure the driver. This sets the driver for future operation, it
+ * may alter the hardware state. Must be called after driver init and
+ * before ANY other driver commands.
+ *
+ * @param driver_handle: A driver handle as returned by igd_driver_init()
+ *
+ * @return <0 on Error
+ * @return 0 On Success
+ */
+int igd_driver_config(igd_driver_h driver_handle);
+
+
+
+/*!
+ * @defgroup init_param Initialization Parameters
+ *
+ * Initialization parameters are passed to igd_module_init() to control
+ * configurable behavior of the HAL. Some parameters are global in that
+ * they have an effect on the entire driver. In addition, there are
+ * parameters that are specific to a display. These parameters are provided
+ * in a list with each list entry representing a defined "port number" as
+ * follows shown here:
+ *
+<PRE>
+                                        /|-----------|
+                                       / | Fp Info   |
+                                      /  |-----------|
+        |----------|   /|---------|  /
+        | Params   |  / | Display | /    |-----------|
+        |          | /  | Param 1 |/     | DTD Array |
+        |          |/   |---------|\     |-----------|
+        |----------|\               \
+                     \  |---------|  \   |-----------|
+                      \ | Display |   \  | Attribute |
+                       \| Param N |    \ | Array     |
+                        |---------|     \|-----------|
+</PRE>
+ *
+ * The port numbers are mapped to hardware specific outputs as defined
+ * here:
+ *
+ * 830M and later Port numbers:
+ *   - 1 DVO A port
+ *   - 2 DVO B port
+ *   - 3 DVO C port
+ *   - 4 Internal LVDS port
+ *   - 5 Analog port
+ *
+ *   On 835: If RGBA is used (DVO B & C together), then use DVO B number
+ *   to specify any parameter for it.
+ *
+ * 810/815 Port numbers:
+ *   - 3 DVO port
+ *   - 5 Analog port
+ *
+ * NOTE: The permanence of the Params data structure that is passed from
+ * the IAL to the HAL in igd_module_init API is not guaranteed by the IAL
+ * Therefore, the different HAL modules should use the data out of this
+ * data structure only until igd_module_init and not after that.
+ * @{
+ */
+
+/*!
+ * This parameter, when set, will cause the driver to save the current
+ * register state of the device prior to altering it in any way. This
+ * will allow the state of the device to be reapplied at exit time.
+ */
+#define IGD_DRIVER_SAVE_RESTORE   0x01
+
+/*!
+ * @name Per-Display Present Params Flags
+ * @anchor present_params_flags
+ *
+ * These flags are used to identify which parameters are being provided to
+ * the HAL. If a bit is not set in the _igd_display_params::present_params
+ * variable the parameters will not be read by the HAL and the default
+ * behavior will be used instead.
+ *
+ * - IGD_PARAM_DDC_GPIO Parameter to select non-standard GPIO pair for DDC.
+ * - IGD_PARAM_DDC_SPEED Parameter to select non-standard DDC speed.
+ * - IGD_PARAM_DDC_DAB Parameter to select the Device Address Byte to use for
+ *     DDC communication
+ * - IGD_PARAM_I2C_GPIO Parameter to select non-standard GPIO pair for i2c.
+ * - IGD_PARAM_I2C_SPEED Parameter to select non-standard I2C speed.
+ * - IGD_PARAM_DAB Parameter to select the Device Address Byte to use for I2C
+ *     communication.
+ * - IGD_PARAM_FP_INFO Parameter to provide non-detectable Flat Panel
+ *     configuration data.
+ * - IGD_PARAM_DTD_LIST Parameter to provide a Detailed Timing List for a
+ *     display.
+ * - IGD_PARAM_ATTR_LIST Parameter to provide a set of Port Driver Attributes
+ *     to use during init.
+ *
+ * @{
+ */
+#define IGD_PARAM_DDC_GPIO        0x00000001
+#define IGD_PARAM_DDC_SPEED       0x00000002
+#define IGD_PARAM_DDC_DAB         0x00000004
+#define IGD_PARAM_I2C_GPIO        0x00000008
+#define IGD_PARAM_I2C_SPEED       0x00000010
+#define IGD_PARAM_DAB             0x00000020
+#define IGD_PARAM_FP_INFO         0x00000040
+#define IGD_PARAM_DTD_LIST        0x00000080
+#define IGD_PARAM_ATTR_LIST       0x00000100
+/*! @} */
+
+
+/*!
+ *
+ *
+ *
+ * @note Any changes to the above number assignment will break the driver.
+ *       If change is required, make sure to change the port numbers in
+ *       port tables.
+ *
+ */
+
+/* The method for controlling the flat panel power. The options include:
+ * no support or the Port Driver handles flat panel power. */
+#define IGD_PARAM_FP_PWR_METHOD_NONE 0
+#define IGD_PARAM_FP_PWR_METHOD_PD   1
+
+/*!
+ * @brief Port-specific color correction information
+ *
+ * Initialization parameter passed as part of igd_module_init() to provide
+ * information about an attached display device. One color_correct_info
+ * is provided for each display port.
+ *
+ */
+typedef struct _igd_param_color_correct_info {
+	/*! @brief RED value for GAMMA */
+	unsigned short gamma_r;
+	/*! @brief GREEN value for GAMMA */
+	unsigned short gamma_g;
+	/*! @brief BLUE value for GAMMA */
+	unsigned short gamma_b;
+	/*! @brief RED value for BRIGHTNESS */
+	unsigned short brightness_r;
+	/*! @brief GREEN value for BRIGHTNESS */
+	unsigned short brightness_g;
+	/*! @brief BLUE value for BRIGHTNESS */
+	unsigned short brightness_b;
+	/*! @brief RED value for CONTRAST */
+	unsigned short constrast_r;
+	/*! @brief GREEN value for CONTRAST */
+	unsigned short constrast_g;
+	/*! @brief BLUE value for CONTRAST */
+	unsigned short constrast_b;
+} igd_param_color_correct_info_t;
+
+
+
+/*!
+ * @brief Flat Panel Information
+ *
+ * Initialization parameter passed as part of igd_module_init() to provide
+ * information about an attached Flat Panel (typically LVDS). One fp_info
+ * is provided for each display port, and is only used when the
+ * IGD_PARAM_FP_INFO flag is set in the _igd_display_params::present_params
+ *
+ */
+typedef struct _igd_param_fp_info {
+	/*! @brief Flat panel width */
+	unsigned long fp_width;
+	/*! @brief Flat panel height */
+	unsigned long fp_height;
+	/*! @brief Flat Panel Power Method */
+	unsigned long fp_pwr_method;
+	/*!
+	 * @brief Min time delay in miliseconds between VDD active and clock/data
+	 * active.
+	 */
+	unsigned long fp_pwr_t1;
+	/*!
+	 * @brief Min time delay in miliseconds between clock/data active and
+	 * backlight enable.
+	 */
+	unsigned long fp_pwr_t2;
+	/*!
+	 * @brief Min time delay in miliseconds between Backlight disable and
+	 * clock/data inactive
+	 */
+	unsigned long  fp_pwr_t3;
+	/*!
+	 * @brief Min time delay in miliseconds between clock/data inactive and
+	 * VDD inactive.
+	 */
+	unsigned long  fp_pwr_t4;
+	/*!
+	 * @brief Min time delay in miliseconds between VDD inactive and
+	 * VDD active.
+	 */
+	unsigned long  fp_pwr_t5;
+} igd_param_fp_info_t;
+
+/*!
+ * @brief Per-display init-time list of DTDs.
+ *
+ * In the case of EDID-less display device, this parameter provides
+ * the DTD (Detailed Timing Descriptor) list to the HAL during initialization.
+ */
+typedef struct _igd_param_dtd_list {
+	/*! @brief number of DTDs */
+	unsigned long  num_dtds;
+	/*! @brief DTD list */
+	igd_display_info_t  *dtd;
+} igd_param_dtd_list_t;
+
+/*!
+ * @brief Port driver attribute
+ */
+typedef struct _igd_param_attr {
+	/*! @brief See @ref attr_id_defs for predefined IDs */
+	unsigned long  id;
+	/*! @brief value or index(incase of list type attr) */
+	unsigned long  value;
+} igd_param_attr_t;
+
+/*!
+ * @brief Port driver init-time attribute list
+ *
+ * This data structure is used during HAL initialization. It should be
+ * populated with any port driver attributes that were modified and saved
+ * in a prior use of the HAL.
+ */
+typedef struct _igd_param_attr_list {
+	/*! @brief  number of attributes in the list */
+	unsigned long  num_attrs;
+	/*! @brief IAL allocated attribute list */
+	igd_param_attr_t *attr;
+} igd_param_attr_list_t;
+
+
+
+/*!
+ * @brief Per-Display Init-time configuration parameters.
+ *
+ * These parameters are provided as an array during igd_module_init().
+ * They allow the default behavior of the driver to be altered on a
+ * per-display basis. They are input-only to provide data
+ * about non-standard hardware configurations and persistant driver state.
+ */
+typedef struct _igd_display_params {
+	/*! @brief Port to which these parameters apply. See @ref init_param */
+	unsigned long port_number;
+	/*! @brief parameters present bitfield: See @ref present_params_flags */
+	unsigned long present_params;
+	unsigned long flags;
+	/*!
+	 * @brief Timing sources to use with Edid displays.
+	 * See @ref advanced_edid
+	 */
+	unsigned short edid_avail;
+	/*!
+	 * @brief Timings sources to use with Edid-less displays.
+	 * See @ref advanced_edid
+	 */
+	unsigned short edid_not_avail;
+	unsigned long ddc_gpio;       /* DDC GPIO pin pair number 0..6 */
+	unsigned long ddc_speed;      /* DDC speed in KHz to read EDID */
+	unsigned long ddc_dab;        /* DDC DAB to read EDID from display device */
+	unsigned long i2c_gpio;       /* I2C GPIO pin pair number 0..6 */
+	unsigned long i2c_speed;      /* I2C speed in KHz to read EDID */
+	unsigned long i2c_dab;        /* I2C DAB to communicate with DVO device */
+	igd_param_fp_info_t fp_info;  /* Connected FP Info */
+	/*!
+	 * DTD parameter: Incase of EDID-less display device, this parameter
+	 * provides the DTD (Detailed Timing Descriptor) list
+	 */
+	igd_param_dtd_list_t dtd_list;
+
+	igd_param_attr_list_t attr_list;
+} igd_display_params_t;
+
+/*!
+ * @name Advanced Edid Flags
+ * @anchor advanced_edid
+ *
+ * Flags to use with edid_avail and edid_not_avail:
+ * perport edid_avail/edid_not_avail
+ *
+ * IGD_DISPLAY_USE_STD_TIMINGS:
+ *   If not set: Do not use driver built-in standard timings
+ *   If set:     Use driver built-in standard timings
+ *
+ * IGD_DISPLAY_USE_EDID:  not applicable to edid_not_avail
+ *   If not set: Do not use EDID block
+ *   If set:     Use EDID block and filter modes
+ *
+ * IGD_DISPLAY_USE_USERDTDS:
+ *   If not set: Do not use user-DTDs
+ *   If set:     Use user-DTDs.
+ *
+ * @{
+ */
+#define IGD_DISPLAY_USE_STD_TIMINGS    0x1
+#define IGD_DISPLAY_USE_EDID           0x2
+#define IGD_DISPLAY_USE_USERDTDS       0x4
+/*! @} */
+
+
+/* Flags for igd_display_params_t->flags*/
+#define IGD_DISPLAY_READ_EDID     0x00000001  /* igd_display_params_t.flags */
+
+/*!
+ * @anchor display_flags_def
+ *
+ * These flags may be used in the display_flags member of the
+ * igd_params_t data structure.
+ *
+ */
+#define IGD_DISPLAY_MULTI_DVO     0x00000002  /* igd_param_t.display_flags  */
+#define IGD_DISPLAY_DETECT        0x00000004  /* igd_param_t.display_flags  */
+#define IGD_DISPLAY_FB_BLEND_OVL  0x00000008  /* igd_param_t.display_flags  */
+#define IGD_DISPLAY_BATCH_BLITS   0x00000010
+	/*! @brief enable dynamic blending of display frame buffer with overlay */
+
+
+
+/*!
+ * @brief Init-Time Driver Parameters
+ *
+ * The igd_param_t data structure contains  global init-time static parameters
+ * to impact the behavior of the whole driver. They are provided to the driver
+ * during module initialization to control overall driver behavior.
+ *
+ *
+ *           VERY IMPORTANT!!! CHANGES TO DEFINITION OF THIS STRUCTURE AND
+ *           ITS MEMBER STRUCTURES MUST BE FOLLOWED BY UPDATES TO THE
+ *           FOLLOWING COMPONENTS / FILES:
+ *                       1. ssigd/ial/vbios/usrbld/igd_uinit.h
+ *                       2. ssigd/ial/vbios/src/core/user_config.c
+ *                       3. pcf2iegd tool (gens user_config.c/h for usr-bld)
+ *                       4. CED tool (generates user_config.c/h for usr-bld)
+ *
+ *
+ *
+ * See igd_module_init()
+ */
+typedef struct _igd_param {
+	/*! @brief Maximum pages taken by the driver for offscreen memory */
+	unsigned long        page_request;
+	/*! @brief Maximum pages reserved for the framebuffer. */
+	unsigned long        max_fb_size;
+	/*! @brief Boolean option to preserve initial hardware state */
+	unsigned char        preserve_regs;
+	/*! @ref display_flags_def "Display Flags" */
+	unsigned long        display_flags;
+	/*!
+	 * @brief Port detection order.
+	 *
+	 * HAL will detect the displays in the  order mentioned and also allocate
+	 * in the same order if found.
+	 *
+	 * Example: To detect/allocate in the order on 855:
+	 * -# DVOB PORT
+	 * -# ANALOG PORT
+	 * -# LVDS PORT
+	 * then specify port_number[] = {2, 5, 4, 0};
+	 *
+	 * @note Set port_number[] = {0, 0, 0, 0}; to work in the default order.
+	 *
+	 * @note If a invalid number is specified then it will be skipped.
+	 */
+	unsigned long port_order[IGD_MAX_PORTS];
+
+	/*! Contains the Per-Display init-time parameters. */
+	igd_display_params_t display_params[IGD_MAX_PORTS];
+
+	/*! @brief RGB color that will be used while clearing the framebuffer */
+	unsigned long        display_color;
+
+    unsigned long       quickboot;
+    int                 qb_seamless;
+    unsigned long       qb_video_input;
+    int                 qb_splash;
+
+	/*! Override interrupt support and revert to polling */
+	int                 polling;
+	unsigned long 		ref_freq;
+	int 				tuning_wa;
+	unsigned long 		clip_hw_fix;
+
+	
+	/* Async flip flickering workaround enable */
+	unsigned long		async_flip_wa;
+	
+	/*
+	 * Enable override of following registers when en_reg_override=1.
+	 * Display Arbitration, FIFO Watermark Control, GVD HP_CONTROL,
+	 * Bunit Chickenbits, Bunit Write Flush, Display Chickenbits
+	 */
+	unsigned long		en_reg_override;
+	unsigned long		disp_arb;
+	unsigned long		fifo_watermark1;
+	unsigned long		fifo_watermark2;
+	unsigned long		fifo_watermark3;
+	unsigned long		fifo_watermark4;
+	unsigned long		fifo_watermark5;
+	unsigned long		fifo_watermark6;
+	unsigned long		gvd_hp_control;
+	unsigned long		bunit_chicken_bits;
+	unsigned long		bunit_write_flush;
+	unsigned long		disp_chicken_bits;
+	int					punt_to_3dblit;
+
+} igd_param_t;
+
+typedef struct {
+	unsigned debug : 1;
+	unsigned ddk_version : 16;
+	unsigned emgd_version : 15;
+} igd_build_config_t;
+
+/*! @} */
+
+/*!
+ *
+ *  Initializes individual modules to a runable state. Init time parameters
+ * may be provided to alter the default behavior of the driver.
+ * See @ref init_param
+ *
+ * The dispatch table for all graphics operations is returned. The dispatch
+ * table may return NULL pointers for unsupported functions due to
+ * optional modules. This dispatch table is used to access HAL functionality
+ * throughout the life of the driver.
+ * See @ref _igd_dispatch
+ *
+ * @param driver_handle as returned from igd_driver_init().
+ * @param dsp dispatch table to be populated during the call.
+ * @param params Input parameters to alter default behavior.
+ *   See @ref init_param
+ *
+ * @return 0 Success
+ * @return <0 on Error
+ */
+int igd_module_init(igd_driver_h driver_handle,
+	igd_dispatch_t **dsp,
+	igd_param_t *params);
+
+
+
+/*!
+ * @name Framebuffer Capabilities
+ * @anchor fb_caps
+ *
+ * FB caps are an indication of large feature sets that will or will not
+ * be available based on FB pixel format. This allows an IAL to intelligently
+ * configure itself to the appropriate setup before setting a display
+ * mode.
+ * FB caps are returned from a call to igd_get_config_info().
+ *
+ * - IGD_CAP_BASIC_2D This capability bit indicates that the device is capable
+ *    of performing basic 2d acceleration.
+ * - IGD_CAP_FULL_2D This capability bit indicates that the device is capable
+ *    of performing full 2d acceleration.
+ * - IGD_CAP_BLEND This capability bit indicates that the device is capable of
+ *    performing the blend() function to the framebuffer.
+ *
+ * @{
+ */
+#define IGD_CAP_BASIC_2D  0x01
+#define IGD_CAP_FULL_2D  (0x02 | IGD_CAP_BASIC_2D)
+#define IGD_CAP_BLEND     0x04
+/*! @} */
+
+
+/*!
+ * @brief Device Capabilities based on FB mode
+ *
+ * This structure reports the Framebuffer capabilities on a pixel format
+ * basis. An IAL should check these capabilities before using acceleration
+ * features. This structure is returned as part of the _igd_config_info
+ * information from the igd_get_config_info() call.
+ *
+ * @see pixel_formats
+ */
+typedef struct _igd_fb_caps {
+	/*! @brief The framebuffer pixel format that these caps reference */
+	unsigned long pixel_format;
+	/*! @brief The capability bits as defined by @ref fb_caps */
+	unsigned long caps;
+} igd_fb_caps_t;
+
+/*!
+ * @brief Static HAL configuration data
+ *
+ * Config info contains the static configuration information for the device
+ * that is found during the call to igd_driver_config(). It is obtained
+ * with a call to igd_get_config_info() which may be done before or after
+ * module configuration with limited success.
+ */
+typedef struct _igd_config_info {
+	/*! @brief The Base MMIO physical (Bus) address. */
+	unsigned long mmio_base_phys;
+	/*! @brief The Base MMIO virtual address. */
+	unsigned char *mmio_base_virt;
+	/*! @brief The Base Video Memory physical (Bus) address. */
+	unsigned long gtt_memory_base_phys;
+	/*! @brief The Base Video Memory virtual address. */
+	unsigned char *gtt_memory_base_virt;
+	/*! @brief The Video Memory Size. */
+	unsigned long gtt_memory_size;
+	/*! @brief The number of display planes supported by the device. */
+	unsigned long num_dsp_planes;
+	/*! @brief The number of display pipes supported by the device. */
+	unsigned long num_dsp_pipes;
+	/*! @brief The number of currently active display ports. */
+	unsigned long num_act_dsp_ports;
+	/*! @brief Caps, terminated with PF = 0 */
+	igd_fb_caps_t *fb_caps;
+	/*! @brief The device revision id. */
+	unsigned long revision_id;
+	/*! @brief HW status page offset (priviledged use only) */
+	unsigned long hw_status_offset;
+	/*! @brief The base of stolen memory */
+	unsigned long stolen_memory_base_virt;
+	/* pixel format that matches the bpp that was passed in */
+	unsigned long pixel_format;
+	/* port-specific rotation read from DisplayID */
+	igd_DID_rotation_info_t displayid_rotation[IGD_MAX_PORTS];
+} igd_config_info_t;
+
+
+/*!
+ * @brief Static GTT configuration data
+ *
+ * This holds the configuration of the GTT and the information
+ * required to handle video memory allocation/free.
+ *
+ * FIXME: There is a lot of duplication with information stored
+ * else were (like igd_config_info_t) that needs to be cleaned up.
+ */
+typedef struct _igd_gtt_info_t {
+	unsigned long gatt_start;
+	unsigned long gatt_pages;
+	unsigned long gtt_start;
+	unsigned long gtt_pages;
+	unsigned long gtt_phys_start;
+	unsigned long stolen_mem_base;
+	unsigned long stolen_mem_size;
+	unsigned long stolen_pages;
+	unsigned long pge_ctl;
+	unsigned short gmch_ctl;
+	unsigned long *gtt_mmap;
+	void *vram_virt;
+	unsigned long initialzied;
+	void *scratch_page;
+} igd_gtt_info_t;
+
+
+
+/*!
+ * The igd_get_config_info() function call can be used to get static
+ * configuration information details that the IAL may need. This
+ * function may be called prior to igd_module_init() with limited
+ * success; however, it is recommeneded that it be called after the
+ * modular HAL components have been initialized.
+ *
+ * In addition to static configuration there may be dynamic configuration
+ * details that can be queried at any time after igd_driver_config().
+ * These are defined with unique identifiers and are queried one at a
+ * time with igd_get_param().
+ *
+ *  @param driver_handle as retuned from igd_driver_init()
+ *  @param config_info Populated with hardware information during the call..
+ *
+ *  @return 0 Success
+ *  @return -IGD_INVAL Error
+ */
+int igd_get_config_info(igd_driver_h driver_handle,
+	igd_config_info_t *config_info);
+
+
+
+/*!
+ * @defgroup runtime_param Runtime Parameter Control
+ *
+ * HAL parameters may be queried and set at runtime using the
+ * _igd_dispatch::get_param() and _igd_dispatch::set_param() dispatch functions
+ * (when called after initialization) or the
+ * igd_get_param() and igd_set_param() functions when called during
+ * initialization.
+ * Some implemtations may not support all parameters so IAL's must handle
+ * errors. Additionally, some parameters are hardware specific and of no use to
+ * general purpose IALs. These should only be used by IALs with extensive
+ * hardware knowledge (OpenGL, D3D, etc)
+ *
+ * @{
+ */
+
+/*!
+ * @name Runtime Parameter Defines
+ *
+ * - IGD_PARAM_PANEL_ID Primary Panel ID
+ *    This is a unique Flat Panel Identifier that is obtained from firmware.
+ *    The IAL may use this information to send in Detailed Timing Descriptors
+ *    to igd_module_init(). This facilitates the use of multiple local Flat
+ *    panel configurations without EDID. When available this parameter may
+ *    be queried prior to igd_module_init().
+ * - IGD_PARAM_MEM_RESERVATION Bios memory reservation.
+ *    This is the amount (in bytes?) of memory that the bios has already
+ *    installed in the Gart prior to driver load. It is used when a
+ *    non-standard bios or firmware has pre-allocated an undetectable amount
+ *    of video memory for splash screen use. When available this parameter can
+ *    be queried prior to igd_module_init().
+ * - IGD_PARAM_DEBUG_MASK Debug Printing Mask.
+ *    This parameter is read/write and may be altered at any time after
+ *    igd_driver_init(). It is a bitfield to control different printing
+ *    groups for debug builds.
+ * - IGD_PARAM_PORT_LIST A bitfield used by the vBIOS to override the
+ *    display detect capabilities in the driver.
+ * - IGD_PARAM_HW_CONFIG Hardware configuration Bitfield
+ *    contains one of these dependeing on platform:
+ *    IGD_ALM_HW_CONFIG_BIN or IGD_NAP_HW_CONFIG_BIN both of which indicate
+ *    the presence and availability of the hardware binner. This value should
+ *    be queried and set (removing the bit) by an IAL claiming use of the
+ *    binner.
+ * - IGD_PARAM_INTR_STATUS Unknown FIXME document this
+ *
+ * @{
+ */
+#define IGD_PARAM_PANEL_ID        0x01
+#define IGD_PARAM_MEM_RESERVATION 0x02
+#define IGD_PARAM_DEBUG_MASK 0x03
+#define IGD_PARAM_PORT_LIST  0x04
+#define IGD_PARAM_GFX_FREQ  0x05
+#define IGD_PARAM_SET_LVDS  0x06
+#define IGD_PARAM_HW_CONFIG 0x1000
+#define  IGD_ALM_HW_CONFIG_BIN 0x1
+#define  IGD_NAP_HW_CONFIG_BIN 0x1
+#define IGD_PARAM_INTR_STATUS 0x1001
+
+/*! @} */
+
+/*!
+ * Gets the value of a runtime driver parameter. These parameters are
+ * each defined with a unique ID and may be altered at runtime.
+ *
+ * Note: There is a wrapper for this function in the dispatch table that
+ * takes a display instead of a driver handle. This version is for use
+ * when displays are not yet available.
+ *
+ * @bug Runtime parameter documentation needs updates
+ *
+ * @return 0 Success
+ * @return -IGD_INVAL Error
+ */
+int igd_get_param(igd_driver_h driver_handle,
+	unsigned long id,
+	unsigned long *value);
+
+/*!
+ * Sets the value of a runtime driver parameter. These parameters are
+ * each defined with a unique ID and may be altered at runtime.
+ *
+ * Note: There is a wrapper for this function in the dispatch table that
+ * takes a display instead of a driver handle. This version is for use
+ * when displays are not yet available.
+ *
+ * @return 0 Success
+ * @return  -IGD_INVAL Error
+ */
+int igd_set_param(igd_driver_h driver_handle,
+	unsigned long id,
+	unsigned long value);
+
+/*! @} Runtime Param Group */
+/*! @} Init Group */
+
+
+/*!
+ * @ingroup cleanup
+ * @brief Shuts down the HAL
+ *
+ * This function shuts down the HAL and frees and remaining resources.
+ * It should be called at driver exit to leave the hardware in a safe
+ * configuration.
+ *
+ * @param driver_handle The driver handle returned from igd_driver_init().
+ *
+ * @return void
+ */
+void igd_driver_shutdown(igd_driver_h driver_handle);
+
+/*!
+ * @ingroup cleanup
+ * @brief Shuts down the HAL
+ *
+ * This function shuts down the HAL and frees and remaining resources.
+ * It should be called at driver exit to leave the hardware in a safe
+ * configuration.
+ *
+ * @param driver_handle The driver handle returned from igd_driver_init().
+ *
+ * @return void
+ */
+void igd_driver_shutdown_hal(igd_driver_h driver_handle);
+
+
+/*!
+ * @ingroup cleanup
+ * @brief Query 2D capability of the hardware.
+ *
+ * This function query the hardware whether given capabilities value 
+ * (caps_val) is supported by hardware.
+ *
+ * @param driver_handle The driver handle returned from igd_driver_init().
+ *
+ * @return void
+ */
+void igd_query_2d_caps_hwhint(igd_driver_h driver_handle, 
+			unsigned long caps_val,
+			unsigned long *status);
+
+
+
+/* 2D capabilities to query */
+#define IGD_2D_CAPS_BLT                 0
+  	 
+/* Output of 2D capabilities to query */
+#define IGD_2D_HW_DISABLE                       0
+#define IGD_2D_HW_ENABLE                        1
+#define IGD_2D_CAPS_UNKNOWN                     2
+  	 
+
+
+/*!
+ * @addtogroup power_group
+ * @{
+ */
+
+/*!
+ * @name Driver Save Flags
+ * @anchor driver_save_flags
+ *
+ * Flags for use with dispatch->driver_save()
+ * @{
+ */
+#define IGD_REG_SAVE_VGA       0x00001
+#define IGD_REG_SAVE_DAC       0x00002
+#define IGD_REG_SAVE_MMIO      0x00004
+#define IGD_REG_SAVE_RB        0x00008
+#define IGD_REG_SAVE_VGA_MEM   0x00010
+#define IGD_REG_SAVE_MODE      0x00020
+#define IGD_REG_SAVE_BACKLIGHT 0x00040
+#define IGD_REG_SAVE_3D        0x00080
+#define IGD_REG_SAVE_GTT       0x00100
+#define IGD_REG_SAVE_TYPE_REG  0x10000
+#define IGD_REG_SAVE_TYPE_CON  0x20000
+#define IGD_REG_SAVE_TYPE_MISC 0x40000
+#define IGD_REG_SAVE_TYPE_MASK 0xF0000
+
+#define IGD_REG_SAVE_ALL (IGD_REG_SAVE_VGA | IGD_REG_SAVE_DAC |  \
+		IGD_REG_SAVE_MMIO | IGD_REG_SAVE_RB | IGD_REG_SAVE_VGA_MEM | \
+		IGD_REG_SAVE_MODE | IGD_REG_SAVE_BACKLIGHT | IGD_REG_SAVE_3D | \
+		IGD_REG_SAVE_GTT )
+
+/*!
+ * @note: This macro does not save the mode (i2c) regs. You have to
+ * explicitly ask for that too if you want it.
+ */
+#define IGD_REG_SAVE_STATE (IGD_REG_SAVE_VGA | IGD_REG_SAVE_DAC | \
+		IGD_REG_SAVE_MMIO | IGD_REG_SAVE_RB | IGD_REG_SAVE_VGA_MEM | \
+		IGD_REG_SAVE_GTT )
+/*! @} */
+
+
+/*! @} */
+
+#endif /* _IGD_INIT_H_ */
diff --git a/drivers/gpu/drm/emgd/include/igd_interrupt.h b/drivers/gpu/drm/emgd/include/igd_interrupt.h
new file mode 100644
index 0000000..6886a20
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_interrupt.h
@@ -0,0 +1,300 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_interrupt.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  The is the IGD exported interrupt access functions. It should be included
+ *  by client drivers making use of interrupt functionality of IGD.
+ *  This file Should NOT be included by any IGD modules because in some
+ *  IGD environments the interrupt module will not be available.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_INTERRUPT_H
+#define _IGD_INTERRUPT_H
+
+#include <igd_mode.h>
+
+typedef struct _oal_callbacks {
+
+	void (*spin_lock_irqsave)(void *lock);
+	void (*spin_unlock_irqrestore)(void *lock);
+	void (*spin_lock_isr)(void *lock);
+	void (*spin_unlock_isr)(void *lock);
+	void (*spin_lock)(void *lock);
+	void (*spin_unlock)(void *lock);
+} oal_callbacks_t;
+
+#define CB_FUNC(a, b, c) if(a && a->b) { a->b(c); }
+
+/* Responses returned to the client from drm */
+#define INT_INVALID  -1
+#define INT_NOOP      0
+#define INT_CLEARED   1
+#define INT_HANDLED   2
+#define INT_READ      3
+#define INT_STORED    4
+#define INT_TIMEOUT   5
+
+/* Response from the ISR helper to the ISR routine */
+#define ISR_NEED_DPC  0
+#define ISR_HANDLED   1
+#define ISR_NOT_OURS  2
+
+typedef struct _interrupt_data {
+
+	void *irqmask_lock;
+
+	unsigned char *msvdx_reg;
+	unsigned long sgx_irq_mask;
+	unsigned long sgx_irq_mask2;
+	unsigned long vdc_irq_mask;
+	unsigned long msvdx_irq_mask;
+	int irq_enabled;
+
+	/* condition to wake up on */
+	unsigned int event_present;
+
+	/* interrupts that have already occured */
+	unsigned int out_vdc;
+
+	unsigned int out_sgx;
+	unsigned int out_sgx2;
+
+	unsigned int out_mtx;
+} interrupt_data_t;
+
+
+/*----------------------------------------------------------------------
+ * Typedef: igd_interrupt_handler_t
+ *
+ * Description:
+ *  This function type is used for OS independent interrupt handlers
+ *  that will be called by the hal to handle a requested interrupt.
+ *
+ * Members:
+ *
+ *----------------------------------------------------------------------
+ */
+typedef void (igd_interrupt_handler_t)(unsigned long type,
+	void *call_data,
+	void *user_data);
+
+
+/*----------------------------------------------------------------------
+ * Typedef: igd_interrupt_t
+ *
+ * Description:
+ *  An opaque handle to identify an interrupt to be handled
+ *
+ * Members:
+ *
+ *----------------------------------------------------------------------
+ */
+typedef void * igd_interrupt_t;
+
+#define IGD_INTERRUPT_VBLANK 0x1
+#define IGD_INTERRUPT_SYNC   0x2
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  isr_helper
+ *
+ * Description:
+ *  This function helps the OAL/DRM module in doing all chipset specific
+ *  functionality like register sets when an ISR is fired
+ * Parameters:
+ *	void
+ * Returns:
+ *  int - 0 on the interrupt was handled and we need to queue a DPC for it
+ *      - 1 on the interrupt was handled but wasn't one to do further
+ *          processing on
+ *      - 2 on failure
+ *----------------------------------------------------------------------
+ */
+int isr_helper(void);
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  unmask_int_helper
+ *
+ * Description:
+ *  This function helps the OAL/DRM module in unmasking the Interrupt
+ *  registers for a particular chipset so that the Interrupts can start
+ *  firing
+ * Parameters:
+ *	void
+ * Returns:
+ *  int - 0 on SUCCESS
+ *      - 1 on FAILURE
+ *----------------------------------------------------------------------
+ */
+int unmask_int_helper(void);
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  mask_int_helper
+ *
+ * Description:
+ *  This function helps the OAL/DRM module in masking the Interrupt
+ *  registers for a particular chipset so that the Interrupts can stop
+ *  firing
+ * Parameters:
+ *	void
+ * Returns:
+ *  int - 0 on SUCCESS
+ *      - 1 on FAILURE
+ *----------------------------------------------------------------------
+ */
+int mask_int_helper(void);
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  request_int_info_helper
+ *
+ * Description:
+ *  This function helps the OAL module to request interrupt information
+ *  and status
+ * Parameters:
+ *	void *int_info_data
+ * Returns:
+ *  int -  1 on Interrupt events supported and previous events occured
+ *      -  0 on Interrupt events supported but no previous events occured
+ *      - -1 on FAILURE or Interrupt events type not supported
+ *----------------------------------------------------------------------
+ */
+int request_int_info_helper(void *int_info_data);
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  clear_occured_int_helper
+ *
+ * Description:
+ *  This function helps the OAL module to request interrupt information
+ *  and status
+ * Parameters:
+ *	void *int_info_data
+ * Returns:
+ *  void
+ *----------------------------------------------------------------------
+ */
+void clear_occured_int_helper(void *int_info_data);
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  mask_int_helper
+ *
+ * Description:
+ *  This function helps the OAL/DRM module in clearing the cached copy
+ *  of Interrupt data
+ * Parameters:
+ *	void
+ * Returns:
+ *	void
+ *----------------------------------------------------------------------
+ */
+void clear_interrupt_cache(void);
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  dpc_helper
+ *
+ * Description:
+ *  This function helps the OAL/DRM module in doing all chipset specific
+ *  functionality like register sets when an DPC is fired
+ * Parameters:
+ *  interrupt_data_t **int_data
+ * Returns:
+ *  int - 0 on SUCCESS
+ *      - 1 on FAILURE
+ *----------------------------------------------------------------------
+ */
+int dpc_helper(interrupt_data_t **int_data);
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  interrupt_init
+ *
+ * Description:
+ *  This function initializees the interrupt helper module
+ * Parameters:
+ *  unsigned short did - Device ID for main video device
+ *  oal_callbacks_t *oal_callbacks_table - Callback for
+ *              spin lock related functions
+ * Returns:
+ *  int - 0 on SUCCESS
+ *      - 1 on FAILURE
+ *----------------------------------------------------------------------
+ */
+int interrupt_init(unsigned short did,
+	oal_callbacks_t *oal_callbacks_table);
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  pre_init_interrupt
+ *
+ * Description:
+ *  This function helps the OAL/DRM module in doing all chipset specific
+ *  functionality like register sets before an ISR is initialized
+ * Parameters:
+ *  unsigned char *virt_mmadr - The MMIO base address
+ * Returns:
+ *  void
+ *----------------------------------------------------------------------
+ */
+void pre_init_interrupt(unsigned char *virt_mmadr);
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  post_init_interrupt
+ *
+ * Description:
+ *  This function helps the OAL/DRM module in doing all chipset specific
+ *  functionality like register sets after an ISR is initialized
+ * Parameters:
+ *  unsigned char *virt_mmadr - The MMIO base address
+ * Returns:
+ *  void
+ *----------------------------------------------------------------------
+ */
+void post_init_interrupt(unsigned char *virt_mmadr);
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  uninstall_interrupt
+ *
+ * Description:
+ *  This function helps the OAL/DRM module in doing all chipset specific
+ *  functionality like register sets for removing Interrupt support
+ * Parameters:
+ *  unsigned char *virt_mmadr - The MMIO base address
+ * Returns:
+ *  void
+ *----------------------------------------------------------------------
+ */
+void uninstall_interrupt(void);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/igd_mode.h b/drivers/gpu/drm/emgd/include/igd_mode.h
new file mode 100644
index 0000000..a3e6da2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_mode.h
@@ -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/drivers/gpu/drm/emgd/include/igd_ovl.h b/drivers/gpu/drm/emgd/include/igd_ovl.h
new file mode 100644
index 0000000..06e826e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_ovl.h
@@ -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/drivers/gpu/drm/emgd/include/igd_pd.h b/drivers/gpu/drm/emgd/include/igd_pd.h
new file mode 100644
index 0000000..2963620
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_pd.h
@@ -0,0 +1,544 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_pd.h
+ * $Revision: 1.13 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_PD_H_
+#define _IGD_PD_H_
+
+#define PD_ATTR_LIST_END     0xFFFFFFFF
+
+#define PD_NAME_SIZE      64
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL    0
+#else
+#define NULL    ((void *)0)
+#endif
+#endif
+
+#ifndef TRUE
+#define TRUE   1
+#endif
+
+#ifndef FALSE
+#define FALSE  0
+#endif
+
+/*!
+ * @addtogroup display_group
+ *
+ * @{
+ */
+
+/*
+ * Display attributes (igd_attr_t):
+ *    id   - Any associated id. See below list for known attribute ids.
+ *
+ *    type - type of the attribute. (RANGE/LIST/BOOL/BUFFER)
+ *
+ *    name - Name of the attribute. For example 'brightness', 'contrast'
+ *
+ *    flags - any flags for the attribute
+ *
+ *            PD_ATTR_FLAG_SETMODE - IGD will set this flag.
+ *                                    If this flag is set, then changing
+ *                                    the attribute value required set mode
+ *                                    operation.
+ *
+ *                                    Caller (IAL) should check for this flag
+ *                                    after calling igd_set_attrs(). If this
+ *                                    flag is set, then IAL has to do a setmode
+ *                                    operation via igd_alter_display().
+ *
+ *            PD_ATTR_FLAG_VALUE_CHANGED - Caller will set this flag.
+ *                                          If this flag is set, means the
+ *                                          attribute value was changed to
+ *                                          the value mentioned.
+ *
+ *                                          Caller will specify SS that the
+ *                                          value was changed.
+ *
+ *            PD_ATTR_FLAG_DONT_APPLY -    If this flag is set, means the
+ *                                          attribute value will be applied
+ *                                          to new value at the time of next
+ *                                          setmode operation.
+ *
+ *
+ *            PD_ATTR_FLAG_USER_INVISIBLE - If this flag is set, means the
+ *                                          attribute is invisible to end-user
+ *                                          and not available for run-time
+ *                                          changes.
+ *
+ *    If the type is PD_ATTR_TYPE_RANGE, then this structure contains further
+ *    details about this attribute (igd_range_attr_t):
+ *      default_value  - Default value
+ *      current_value  - Current value
+ *      min            - Minimum value for this attribute
+ *      max            - Maximum value for this attribute
+ *      step           - Value changes in increments of 'step'
+ *
+ *    If the type is PD_ATTR_TYPE_LIST, then this structure contains further
+ *    details about this attribute (igd_list_attr_t):
+ *      default_index  - this is the index into above list to point
+ *                              default value for this attribute
+ *
+ *      current_index  - this is the index into above list to point
+ *                              current value for this attribute
+ *
+ *      num_entries    - number values avaliable for this list attribute,
+ *                       for example, for TVFormat attribute, the available
+ *                       values can be NTSC, NTSC_M, PAL, PAL_D etc etc...
+ *
+ *      _pad           - [reserved] Pad bytes to make all attributes
+ *                       structures with same size.
+ *
+ *    If the type is PD_ATTR_TYPE_LIST, then there are num_entries structures
+ *    of igd_list_entry_attr_t will be there (igd_list_entry_attr_t):
+ *      name           - name is overloaded for example for TVFormat attribute
+ *                       the names will be "NTSC", "NTSC_M" etc etc...
+ *
+ *      flags          - same as above flags.
+ *
+ *      value          - Internal value for "NTSC", i.e., the #define value.
+ *
+ *      _pad           - [reserved] Pad bytes to make all attributes
+ *                       structures with same size.
+ *
+ *    If the type is PD_ATTR_TYPE_BOOL, then this structure contains further
+ *    details about this attribute (igd_bool_attr_t):
+ *      default_value  - Default value (TRUE/FALSE)
+ *
+ *      current_value  - Current value (TRUE/FALSE)
+ *
+ *      _pad           - [reserved] Pad bytes to make all attributes
+ *                       structures with same size.
+ *
+ *    If the type is PD_ATTR_TYPE_BUFFER, then there is a buffer pointer
+ *    in the structure to pass larger chunks of data. Originator owns the
+ *    buffer.
+ *      buffer_size    - size of the buffer
+ *
+ *      buffer         - pointer to buffer
+ *
+ */
+#define PD_ATTR_TYPE_RANGE      0x1
+#define PD_ATTR_TYPE_LIST       0x2
+#define PD_ATTR_TYPE_BOOL       0x3
+#define PD_ATTR_TYPE_LIST_ENTRY 0x4
+#define PD_ATTR_TYPE_BUFFER     0x5
+
+/*!
+ * @name Attribute ID definitions
+ * @anchor attr_id_defs
+ *
+ *  These IDs specify what the attribute is and also index into the list of
+ * attributes. See get_attrs() and set_attrs() for more information.
+ *
+ * @{
+ */
+#define PD_ATTR_ID_BRIGHTNESS      0x00
+#define PD_ATTR_ID_CONTRAST        0x01
+#define PD_ATTR_ID_HUE             0x02
+#define PD_ATTR_ID_FLICKER         0x03
+#define PD_ATTR_ID_HPOSITION       0x04
+#define PD_ATTR_ID_VPOSITION       0x05
+#define PD_ATTR_ID_HSCALE          0x06
+#define PD_ATTR_ID_VSCALE          0x07
+#define PD_ATTR_ID_TVFORMAT        0x08  /* See below for list of TV formats */
+#define PD_ATTR_ID_DISPLAY         0x09  /* See below for list of displays */
+#define PD_ATTR_ID_LUMA_FILTER     0x0A
+#define PD_ATTR_ID_CHROMA_FILTER   0x0B
+#define PD_ATTR_ID_TEXT_FILTER     0x0C
+#define PD_ATTR_ID_TVOUT_TYPE      0x0E
+#define PD_ATTR_ID_SATURATION      0x0F
+#define PD_ATTR_ID_PANEL_FIT       0x12  /* Up/Down scale yes/no */
+#define PD_ATTR_ID_SCALING_RATIO   0x13
+#define PD_ATTR_ID_FP_BACKLIGHT_EN 0x14  /* Enable Flat panel backlight      */
+#define PD_ATTR_ID_FP_PWR_T1       0x15  /* VDD active - DVO CLK/DATA active */
+#define PD_ATTR_ID_FP_PWR_T2       0x16  /* DVO active - Backlight enable    */
+#define PD_ATTR_ID_FP_PWR_T3       0x17  /* Backlight disable - DVO inactive */
+#define PD_ATTR_ID_FP_PWR_T4       0x18  /* DVO inactive - VDD inactive      */
+#define PD_ATTR_ID_FP_PWR_T5       0x19  /* VDD inactive - VDD active        */
+#define PD_ATTR_ID_PANEL_DEPTH     0x1A  /* Range, 18/24 panel */
+#define PD_ATTR_ID_2_CHANNEL_PANEL 0x1B  /* Boolean, dual-channel panel ? */
+#define PD_ATTR_ID_GANG_MODE       0x1C  /* Boolean, gang display or not? */
+#define PD_ATTR_ID_GANG_MODE_EVEN_ODD 0x1D  /* Boolean, gang display even/odd */
+#define PD_ATTR_ID_REVERSE_DVO_DATA   0x1E  /* Request reverse DVO data order */
+#define PD_ATTR_ID_SHARPNESS       0x1F
+#define PD_ATTR_ID_HW_CONFIG       0x20
+#define PD_ATTR_ID_HORZ_FILTER     0x21
+#define PD_ATTR_ID_VERT_FILTER     0x22
+#define PD_ATTR_ID_FB_GAMMA        0x23
+#define PD_ATTR_ID_FB_BRIGHTNESS   0x24
+#define PD_ATTR_ID_FB_CONTRAST     0x25
+#define PD_ATTR_ID_EXTENSION       0x26
+#define PD_ATTR_ID_2D_FLICKER      0x27
+#define PD_ATTR_ID_ADAPTIVE_FLICKER     0x28
+#define PD_ATTR_ID_HORZ_OVERSCAN        0x29
+#define PD_ATTR_ID_VERT_OVERSCAN        0x2A
+#define PD_ATTR_ID_SSC                  0x2B
+#define PD_ATTR_ID_DOT_CRAWL            0x2C
+#define PD_ATTR_ID_DITHER               0x2D
+#define PD_ATTR_ID_PANEL_PROTECT_HSYNC  0x2E
+#define PD_ATTR_ID_PANEL_PROTECT_VSYNC  0x2F
+#define PD_ATTR_ID_PANEL_PROTECT_PIXCLK 0x30
+#define PD_ATTR_ID_LVDS_PANEL_TYPE      0x31
+#define PD_ATTR_ID_ANALOG_SRC           0x34
+#define PD_ATTR_ID_SCAN_INFO            0x35
+#define PD_ATTR_ID_PICTURE_ASPECT_RATIO 0x36
+#define PD_ATTR_ID_ACTIVE_FORMAT        0x37
+#define PD_ATTR_ID_GANG_MODE_DVOCLKINV  0x38
+#define PD_ATTR_ID_VGA_2X_IMAGE         0x39
+#define PD_ATTR_ID_TEXT_TUNING          0x3A
+#define PD_ATTR_ID_MAINTAIN_ASPECT_RATIO 0x3B
+#define PD_ATTR_ID_FIXED_TIMING         0x3C
+#define PD_ATTR_ID_COLORIMETRY			0x3D   /* HDMI Attributes */
+#define PD_ATTR_ID_PIXEL_REPLICATION	0x3E
+#define PD_ATTR_ID_INTERRUPT_TYPE       0x3F   /* sdvo interrupt type */
+/* Port Driver alternative name */
+#define PD_ATTR_ID_PORT_NAME	        0x44
+/* Port ddc_reg */
+#define PD_ATTR_ID_PORT_DDC_REG			0x45
+#define PD_ATTR_ID_PWM_INTENSITY		0x46
+#define PD_ATTR_ID_INVERTER_FREQ		0x47
+#define PD_ATTR_ID_BLM_LEGACY_MODE		0x48
+#define PD_ATTR_ID_RB_SWAP_MODE			0x49
+//************ port driver attributes defined for ch7036 port driver **************//
+#define PD_ATTR_ID_HFLIP			0x54
+#define PD_ATTR_ID_VFLIP			0x55
+
+//hdmi audio
+#define PD_ATTR_ID_AUDIO_I2S_FORMAT		0x56
+#define PD_ATTR_ID_AUDIO_I2S_POLARITY           0x57
+#define PD_ATTR_ID_AUDIO_I2S_LENGH		0x58
+
+#define PD_ATTR_ID_AUDIO_TYPE			0x59 //1- I2S, 0: SPDIF
+
+//display mode tables supported by ch7036
+#define PD_ATTR_ID_HDMI_OUT_MODE		0x5A
+#define PD_ATTR_ID_DVI_OUT_MODE			0x5B
+#define PD_ATTR_ID_CRT_OUT_MODE			0x5C
+
+
+#define PD_ATTR_ID_DITHER_BYPASS		0x5D //to bypass Dither block - note: PD_ATTR_ID_DITHER is for dither selection: 18-18, 18-24, etc...
+#define PD_ATTR_ID_EDID_BYPASS			0x5E //1: bypass (use fixed built-in table, 0: read panel EDID)
+
+//1:hdmi, 0: dvi- note: PD_ATTR_ID_HDMI_CHANNEL will be  ‘inactive’ after EDID reading is
+//implemented and selected, e.g. PD_ATTR_ID_EDID_BYPASS =0
+#define PD_ATTR_ID_HDMI_CHANNEL			0x5F
+#define PD_ATTR_ID_PLL_REF_DLY			0x60
+#define PD_ATTR_ID_PLL_REF_FBDLY		0x61
+#define PD_ATTR_ID_ROTATE			0x62
+#define PD_ATTR_ID_HSCALE_CRT			0x63
+#define PD_ATTR_ID_VSCALE_CRT			0x64
+
+#define PD_ATTR_ID_LOAD_FIRMWARE		0x65
+#define PD_ATTR_ID_REFRESH			0x66
+#define PD_ATTR_ID_DWNSCAL_BYPASS		0x57 //1.2.5.pd: new pd attributes to handle the downscalling quality issue
+
+
+//************ end of ch7036 defined port driver attribute ********** //
+
+#define PD_ATTR_ID_NUM_IDS			0x67  /* Always make this last */
+
+/*! @} */
+
+/* Bit fields. */
+#define PD_ATTR_FLAG_SETMODE         0x01
+#define PD_ATTR_FLAG_VALUE_CHANGED   0x02
+#define PD_ATTR_FLAG_DONT_SET_IMM    0x04
+#define PD_ATTR_FLAG_USER_INVISIBLE  0x08   /* Attr invisible to enduser */
+#define PD_ATTR_FLAG_PD_INVISIBLE    0x10   /* Attr invisible to PD */
+#define PD_ATTR_FLAG_DYNAMIC         0x20   /* Attribute queried from sDVO */
+#define PD_ATTR_FLAG_NOTUSED         0x80   /* Attribute not used, this flag
+											 * supercedes all other flags */
+#define PD_ATTR_FLAG_NEED_RESTORE	 0x100  /* Reset occured and register value is in limbo.
+												During this time we need to keep
+												the value of the attr in our table
+												unchanged. */
+#define PD_ATTR_FLAG_GENERAL		 0x1000 /* This flag is used by HAL to querry
+											 * general attributes */
+#define PD_QUERY_GENERAL_ATTR		PD_ATTR_ID_NUM_IDS + 2
+/* TVoutput types PD_ATTR_ID_TVOUT_TYPE */
+#define PD_TVOUT_COMPOSITE    0x01
+#define PD_TVOUT_SVIDEO       0x02
+#define PD_TVOUT_COMPONENT    0x03
+#define PD_TVOUT_CPSTSV       0x04          /* Composite and S-Video */
+#define	PD_TVOUT_SCARTRGB     0x05          /* SCART output */
+#define	PD_TVOUT_VGADAC       0x06          /* VGA Outout */
+
+/* TV Standard Option */
+/* Similar TV formats need to have the same last nibble.
+ * Example for PAL the last nibble is 0x2, for NTSC it is
+ * 0x1 and so forth.
+ */
+#define PD_TV_STD_NTSC_M       0x01    /* USA, 75 IRE Setup */
+#define PD_TV_STD_NTSC_M_J     0x11    /* Japan,  0 IRE Setup */
+#define PD_TV_STD_NTSC_433     0x21
+#define PD_TV_STD_NTSC_N       0x31
+
+#define PD_TV_STD_PAL_B        0x02    /* Australia, U.K., N.Z etc */
+#define PD_TV_STD_PAL_G        0x12
+#define PD_TV_STD_PAL_D        0x22
+#define PD_TV_STD_PAL_H        0x32
+#define PD_TV_STD_PAL_I        0x42
+#define PD_TV_STD_PAL_M        0x52
+#define PD_TV_STD_PAL_N        0x62
+#define PD_TV_STD_PAL_60       0x72
+#define PD_TV_STD_PAL_NC       0x82
+
+#define PD_TV_STD_SECAM_L      0x03    /* France */
+#define PD_TV_STD_SECAM_L1     0x13
+#define PD_TV_STD_SECAM_B      0x23
+#define PD_TV_STD_SECAM_D      0x33
+#define PD_TV_STD_SECAM_G      0x43
+#define PD_TV_STD_SECAM_H      0x53
+#define PD_TV_STD_SECAM_K      0x63
+#define PD_TV_STD_SECAM_K1     0x73
+#define PD_TV_STD_SECAM_60     0x83
+
+#define PD_TV_STD_HDTV_480P    0x04
+#define PD_TV_STD_HDTV_720P    0x14
+#define PD_TV_STD_HDTV_1080I   0x24
+
+/* These HDTV defines are added for Int TV in 915GM */
+#define PD_TV_STD_HDTV_480I_59			0x34  /* 59Hz */
+#define PD_TV_STD_HDTV_480P_59			0x44
+#define PD_TV_STD_HDTV_480P_60			0x54
+
+#define PD_TV_STD_HDTV_576I_50			0x64
+#define PD_TV_STD_HDTV_576P_50			0x74
+
+#define PD_TV_STD_HDTV_720P_50			0x84
+#define PD_TV_STD_HDTV_720P_59			0x94
+#define PD_TV_STD_HDTV_720P_60			0xA4
+
+#define PD_TV_STD_HDTV_1080I_50			0xB4
+#define PD_TV_STD_HDTV_1080I_59			0xC4
+#define PD_TV_STD_HDTV_1080I_60			0xD4
+
+#define PD_TV_STD_HDTV_1080P_60			0xE4
+
+/* Defines for SDVO TV */
+#define PD_HDTV_STD_SMPTE_240M_1080i59  0x101
+#define PD_HDTV_STD_SMPTE_240M_1080i60  0x102
+
+#define PD_HDTV_STD_SMPTE_260M_1080i59  0x103
+#define PD_HDTV_STD_SMPTE_260M_1080i60  0x104
+
+#define PD_HDTV_STD_SMPTE_274M_1080i50  0x105
+#define PD_HDTV_STD_SMPTE_274M_1080i59  0x106
+#define PD_HDTV_STD_SMPTE_274M_1080i60  0x107
+#define PD_HDTV_STD_SMPTE_274M_1080p23  0x108
+#define PD_HDTV_STD_SMPTE_274M_1080p24  0x109
+#define PD_HDTV_STD_SMPTE_274M_1080p25  0x10A
+#define PD_HDTV_STD_SMPTE_274M_1080p29  0x10B
+#define PD_HDTV_STD_SMPTE_274M_1080p30  0x10C
+#define PD_HDTV_STD_SMPTE_274M_1080p50  0x10D
+#define PD_HDTV_STD_SMPTE_274M_1080p59  0x10E
+#define PD_HDTV_STD_SMPTE_274M_1080p60  0x10F
+
+#define PD_HDTV_STD_SMPTE_295M_1080i50  0x110
+#define PD_HDTV_STD_SMPTE_295M_1080p50  0x111
+
+#define PD_HDTV_STD_SMPTE_296M_720p59   0x112
+#define PD_HDTV_STD_SMPTE_296M_720p60   0x113
+#define PD_HDTV_STD_SMPTE_296M_720p50   0x114
+
+#define PD_HDTV_STD_SMPTE_293M_480p59   0x115
+#define PD_HDTV_STD_SMPTE_170M_480i59   0x116
+
+#define PD_HDTV_STD_ITURBT601_576i50    0x117
+#define PD_HDTV_STD_ITURBT601_576p50    0x118
+#define PD_HDTV_STD_EIA_7702A_480i60    0x119
+#define PD_HDTV_STD_EIA_7702A_480p60    0x11A
+
+/* Supported display types */
+/* Port drivers for DVO devices shouldn't use
+ *    PD_DISPLAY_CRT,
+ *    PD_DISPLAY_TVOUT_INT,
+ *        and
+ *    PD_DISPLAY_LVDS_INT. These are for internal on board GMCH displays..
+ *
+ * Only following display types are available for port drivers
+ * for DVO devices:
+ *    PD_DISPLAY_CRT_EXT
+ *    PD_DISPLAY_TVOUT
+ *    PD_DISPLAY_TVFP (i.e., PD_DISPLAY_TVOUT|PD_DISPLAY_FP)
+ *    PD_DISPLAY_LVDS_EXT
+ *    PD_DISPLAY_FP
+ *    PD_DISPLAY_RGBA
+ *    PD_DISPLAY_DRGB
+ *
+ * Also port drivers can make new combinations, for example,
+ * if an DVO encoder supports both LVDS and TVOut displays, it can use
+ *    PD_DISPLAY_LVDS_EXT | PD_DISPLAY_TVOUT
+ */
+#define PD_DISPLAY_CRT         0x00000001    /* GMCH on board CRT */
+#define PD_DISPLAY_TVOUT       0x00000002    /* TVOUT display type */
+#define PD_DISPLAY_FP          0x00000004    /* Flat panel type */
+#define PD_DISPLAY_TVFP        0x00000006    /* Codec supports TV + FP */
+#define PD_DISPLAY_RGBA        0x00000008    /* RGBA display */
+#define PD_DISPLAY_LVDS_EXT    0x00000010    /* External local flat panel */
+#define PD_DISPLAY_LVDS_INT    0x00000020    /* GMCH on board LVDS */
+#define PD_DISPLAY_CRT_EXT     0x00000040    /* External CRT display */
+#define PD_DISPLAY_TVOUT_INT   0x00000080    /* GMCH on board TVout */
+#define PD_DISPLAY_HDMI_INT    0x00000100    /* HDMI on board */
+#define PD_DISPLAY_HDMI_EXT    0x00000200    /* External HDMI */
+#define PD_DISPLAY_DP_INT      0x00000400    /* Display Port on board */
+#define PD_DISPLAY_DRGB        0x00000800    /* SDVO DRGB display */
+/* new display types introduced by LVDS converter chip, CH7036 */
+#define PD_DISPLAY_LVDS_LHDV   0x00001000  /* lvds converter- converts lvds signals to 
+												lvds pass-thru, hdmi, dvi, or vga */
+
+
+#ifdef CONFIG_MICRO
+#define PD_MAKE_ATTR(id, type, name, flags, def, cur, a, b, c) \
+	{id, type, flags, def, cur, a, b, c}
+#else
+#define PD_MAKE_ATTR(id, type, name, flags, def, cur, a, b, c) \
+	{id, type, name, flags, def, cur, a, b, c}
+#endif
+
+typedef struct _igd_DID_rotation_info_t {
+	int rotation;
+	int flip;
+} igd_DID_rotation_info_t;
+
+/* IMP NOTE: All below structures should be with same size.
+ *         igd_attr_t            : General attribute structure
+ *         igd_range_attr_t      : Range type attribute structure
+ *         igd_list_attr_t       : List type attribute
+ *         igd_list_entry_attr_t : Entry for a list
+ *         igd_bool_attr_t       : Boolean type attribute
+ *         igd_extension_attr_t  : Extension type attribute
+ *         igd_buffer_attr_t     : Buffer type attribute
+ */
+typedef struct _igd_attr {
+	unsigned long id;
+	unsigned long type;
+#ifndef CONFIG_MICRO
+	char name[32];
+#endif
+	unsigned long flags;
+	unsigned long default_value;
+	unsigned long current_value;
+	unsigned long _pad0;
+	unsigned long _pad1;
+	unsigned long _pad2;
+}igd_attr_t;
+
+typedef struct _igd_range_attr {
+	unsigned long id;
+	unsigned long type;
+#ifndef CONFIG_MICRO
+	char          name[32];
+#endif
+	unsigned long flags;
+	unsigned long default_value;
+	unsigned long current_value;
+	unsigned long min;
+	unsigned long max;
+	unsigned long step;
+}igd_range_attr_t;
+
+typedef struct _igd_list_attr {
+	unsigned long id;
+	unsigned long type;
+#ifndef CONFIG_MICRO
+	char          name[32];
+#endif
+	unsigned long flags;
+	unsigned long default_index;
+	unsigned long current_index;
+	unsigned long num_entries;
+	unsigned long _pad0;
+	unsigned long _pad1;
+}igd_list_attr_t;
+
+typedef struct _igd_list_entry_attr {
+	unsigned long id;
+	unsigned long type;
+#ifndef CONFIG_MICRO
+	char          name[32];
+#endif
+	unsigned long flags;
+	unsigned long value;
+	unsigned long _pad0;
+	unsigned long _pad1;
+	unsigned long _pad2;
+	unsigned long _pad3;
+}igd_list_entry_attr_t;
+
+typedef struct _igd_bool_attr {
+	unsigned long id;
+	unsigned long type;
+#ifndef CONFIG_MICRO
+	char          name[32];
+#endif
+	unsigned long flags;
+	unsigned long default_value;
+	unsigned long current_value;
+	unsigned long _pad0;
+	unsigned long _pad1;
+	unsigned long _pad2;
+}igd_bool_attr_t;
+
+typedef struct _igd_buffer_attr {
+	unsigned long id;
+	unsigned long type;
+#ifndef CONFIG_MICRO
+	char          name[32];
+#endif
+	unsigned long flags;
+	unsigned long buffer_size;
+	void          *buffer;
+	unsigned long _pad0;
+	unsigned long _pad1;
+	unsigned long _pad2;
+} igd_buffer_attr_t;
+
+typedef struct _igd_extension_attr {
+	unsigned long id;
+	unsigned long type;
+#ifndef CONFIG_MICRO
+	char name[32];
+#endif
+	unsigned long flags;
+	unsigned long default_value;
+	unsigned long current_value;
+	igd_attr_t    *extension;
+} igd_extension_attr_t;
+
+
+/*! @} */
+
+#endif /* _IGD_PD_H_ */
diff --git a/drivers/gpu/drm/emgd/include/igd_pi.h b/drivers/gpu/drm/emgd/include/igd_pi.h
new file mode 100644
index 0000000..bc12a5b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_pi.h
@@ -0,0 +1,130 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_pi.h
+ * $Revision: 1.9 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_PI_H
+#define _IGD_PI_H
+
+/* Typedefinitions */
+typedef int        (*pd_register_p)  (void *handle, void *driver);
+typedef void      *(*pd_malloc_p)(unsigned long size);
+typedef void      *(*pd_memset_p)(void *address, int c, unsigned long size);
+typedef void      *(*pd_memcpy_p)(void *dst, void *src, unsigned long size);
+typedef void       (*pd_free_p)  (void *address);
+typedef void       (*pd_usleep_p)(unsigned long usec);
+typedef void       (*pd_ui_usleep_p)(unsigned long usec);
+typedef char      *(*pd_strcpy_p)(char *dest, char const *src);
+typedef int       *(*pd_printf_p)(const char *format, ...);
+typedef int        (*pd_check_attr_p)(void *curr, void *in);
+typedef void      *(*pd_get_attr_p)(void *attr_list,
+		unsigned long num_attrs, unsigned long attr_id, unsigned long flag);
+typedef void *(*pd_get_igd_debug_p)( void );
+typedef unsigned long *(*pd_get_dropped_debug_messages_p)( void );
+typedef void *(*pd_get_debug_log_mutex_p)( void );
+typedef int        (*pd_filter_timings_p)(void *context, void *inlist,
+		void **olist, void *dvo_info, void *display_info);
+
+
+
+/* Data structures to pass callback functions from child to parent */
+typedef struct _igd_main_cb {
+	unsigned long       version;
+	pd_register_p       pd_register;
+	pd_malloc_p         pd_malloc;
+	pd_memset_p         pd_memset;
+	pd_memcpy_p         pd_memcpy;
+	pd_free_p           pd_free;
+	pd_usleep_p         pd_usleep;
+	pd_ui_usleep_p      pd_ui_usleep;
+	pd_strcpy_p         pd_strcpy;
+	pd_check_attr_p     pd_check_attr;
+	pd_get_attr_p       pd_get_attr;
+	pd_filter_timings_p pd_filter_timings;
+	pd_get_igd_debug_p  pd_get_igd_debug;
+	pd_get_debug_log_mutex_p        pd_get_debug_log_mutex;
+	pd_get_dropped_debug_messages_p pd_get_dropped_debug_messages;
+} igd_main_cb_t;
+
+typedef struct _igd_dpd_cb {
+	unsigned long   version;
+} igd_dpd_cb_t;
+
+
+/* Port driver init and exit function type definitions */
+typedef int (*pd_init_p)  (void *);
+typedef int (*pd_exit_p)  (void);
+
+/* Function to register with main driver. */
+int igd_pd_register(void *handle, void *pd_driver);
+
+/* Function to allocate memory */
+void *igd_pd_malloc(unsigned long size);
+
+/* Function to set the memory */
+void *igd_pd_memset(void *address, int c, unsigned long size);
+
+/* Function to copy block of memory */
+void *igd_pd_memcpy(void *dst, void *src, unsigned long size);
+
+/* Functions to free memory */
+void igd_pd_free(void *ptr);
+
+/* Function to sleep in micro seconds. This can be called with millisecond
+ * ranges. */
+void igd_pd_usleep(unsigned long usec);
+
+/* Function to sleep in micro seconds uniterrupted. This can be called with millisecond
+ * ranges. */
+void igd_pd_ui_usleep(unsigned long usec);
+
+
+/* Function to do a string copy */
+char *igd_pd_strcpy(char *dest, char const *src);
+
+/* Function to check value of an attribute */
+int igd_pd_check_attr(void *curr, void *in);
+
+/* This function searches for the requested attr_id in the attribute list
+ * and returns the pointer.
+ *
+ * In case of LIST attribute, it will return the proper list entry. */
+void *igd_pd_get_attr(void *attr_list, unsigned long num_attrs,
+		unsigned long attr_id, unsigned long flag);
+
+int igd_pd_filter_timings(
+	void *context,
+	void *ilist,
+	void **olist,
+	void *dvo,
+	void *display);
+
+void *igd_pd_get_igd_debug( void );
+
+#endif /* _IGD_PI_H */
diff --git a/drivers/gpu/drm/emgd/include/igd_pwr.h b/drivers/gpu/drm/emgd/include/igd_pwr.h
new file mode 100644
index 0000000..3564031
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_pwr.h
@@ -0,0 +1,65 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_pwr.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+
+#ifndef _IGD_PWR_H
+#define _IGD_PWR_H
+
+/*
+ * Device power state defines
+ */
+
+#define IGD_POWERSTATE_D0			0x0
+#define IGD_POWERSTATE_D1			0x1
+#define IGD_POWERSTATE_D2			0x2
+#define IGD_POWERSTATE_D3			0x3
+#define IGD_POWERSTATE_UNDEFINED    0xFFFFFFFF
+
+/*
+ * Graphics Adaptor Power State Defines
+ */
+#define IGD_ADAPTERPOWERSTATE_ON        0x10
+#define IGD_ADAPTERPOWERSTATE_STANDBY   0x11
+#define IGD_ADAPTERPOWERSTATE_SUSPEND   0x12
+#define IGD_ADAPTERPOWERSTATE_OFF       0x13
+#define IGD_ADAPTERPOWERSTATE_HIBERNATE 0x14
+
+
+/*----------------------------------------------------------------------
+ * Function:
+ *  int dispatch->pwr_alter(igd_driver_h driver_handle,
+ *    unsigned int power_state);
+ *
+ * *----------------------------------------------------------------------
+ */
+
+#endif /*_IGD_PWR_H*/
diff --git a/drivers/gpu/drm/emgd/include/igd_rb.h b/drivers/gpu/drm/emgd/include/igd_rb.h
new file mode 100644
index 0000000..3008870
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_rb.h
@@ -0,0 +1,92 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_rb.h
+ * $Revision: 1.7 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Example Usage:
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_RB_H
+#define _IGD_RB_H
+
+#include <igd_mode.h>
+
+/*
+ * Flags for igd_sync()
+ */
+#define IGD_SYNC_BLOCK         0x00000000
+#define IGD_SYNC_NONBLOCK      0x00000001
+/*
+ * No Flush pipe will not issue an MI Flush before the store dword
+ * There is no guarentee that the store dword will not complete before
+ * an earlier command unless the caller is sure that a store dword alone
+ * is sufficient.
+ */
+#define IGD_SYNC_NOFLUSH_PIPE  0x00000010
+/*
+ * Do not flush the render cache as part of this flush. Map Cache will
+ * be invalidated always.
+ */
+#define IGD_SYNC_NOFLUSH_CACHE 0x00000020
+/* Generate a user Interrupt after the sync completes */
+#define IGD_SYNC_INTERRUPT   0x00000040
+/*
+ * Flush the pipe now but delay the cache flush until the
+ * sync is checked.
+ */
+#define IGD_SYNC_DELAY_FLUSH 0x00000080
+/*
+ * Synchronize queue with video decode engine.
+ */
+#define IGD_SYNC_VIDEO       0x00000100
+
+
+/*!
+ * dispatch->get_sync_slot() returns the offset into the status page where
+ * the sync values can be found for a particular display handle.
+ *
+ * This function is to be used by a priviledged IAL only and requires some
+ * knowledge of the underlying behavior of the sync. The intention of this
+ * function is to allow an IAL that already has device knowledge to
+ * check the status of an issued sync call without calling through the HAL.
+ * In some cases (such as OGL) the address space seperation would otherwise
+ * make sync checking through the HAL a cost prohibitive operation.
+ *
+ * @param display_handle pointer to an IGD_DISPLAY pointer returned
+ *    from a successful call to dispatch->allocate_display().
+ *
+ * @param priority One of the IGD_PRIORITY_* defines. This must match
+ *    the define used when issuing the sync. NORMAL priority is the
+ *    only common use case.
+ *
+ * @return 0: Success.
+ * @return -IGD_ERROR_INVAL:  Otherwise
+ */
+typedef int (*_igd_get_sync_slot_fn_t)(igd_display_h display_handle,
+	unsigned int priority,
+	unsigned int *offset);
+
+#endif /* _IGD_RB_H */
diff --git a/drivers/gpu/drm/emgd/include/igd_render.h b/drivers/gpu/drm/emgd/include/igd_render.h
new file mode 100644
index 0000000..c492918
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_render.h
@@ -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/drivers/gpu/drm/emgd/include/igd_reset.h b/drivers/gpu/drm/emgd/include/igd_reset.h
new file mode 100644
index 0000000..6150b6c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_reset.h
@@ -0,0 +1,55 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_reset.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This is the external header file for the reset module. It should be included
+ *  by above IAL for reset functionality on the ssigd HAL layers.
+ *-----------------------------------------------------------------------------
+ */
+
+
+#ifndef _IGD_RESET_H
+#define _IGD_RESET_H
+
+
+/*----------------------------------------------------------------------------
+ * Function:
+ *   int dispatch->reset_alter(igd_driver_h driver_handle);
+ *
+ * Description:
+ *		.
+ * Parameters:
+ *		driver_handle - pointer to main driver context structure.
+ *
+ * Return:
+ *  !0: Pointer to a ring buffer structure upon successful allocation
+ *  0: A ring buffer of specified type can not be allocated, or an
+ *    error occurred during memory allocation for the buffer.
+ *----------------------------------------------------------------------------
+ */
+
+
+#endif /*_IGD_RESET_H*/
diff --git a/drivers/gpu/drm/emgd/include/igd_version.h b/drivers/gpu/drm/emgd/include/igd_version.h
new file mode 100644
index 0000000..a0482a5
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_version.h
@@ -0,0 +1,41 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_version.h
+ * $Revision: 1.217 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF 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  2443
+
+#define IGD_PCF_VERSION   0x00000400
+#endif
diff --git a/drivers/gpu/drm/emgd/include/igd_vga.h b/drivers/gpu/drm/emgd/include/igd_vga.h
new file mode 100644
index 0000000..1f232f0
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/igd_vga.h
@@ -0,0 +1,65 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: igd_vga.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  Header file for common VGA registers and macros.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _IGD_VGA_H
+#define _IGD_VGA_H
+
+#ifdef CONFIG_MICRO
+#define VB_CODE_SEG __based( __segname("_CODE"))
+#else
+#define VB_CODE_SEG
+#endif
+
+/* The Maximum VGA Mode Number as specified in the IGD Mode Table. */
+#define VGA_MODE_NUM_MAX 0x1C
+
+typedef struct vga_mode_data {
+	unsigned char  cols;
+	unsigned char  rows;                 /* #rows-1 */
+	unsigned char  char_height;
+	unsigned short video_buff_size;
+	unsigned char  sr_regs[4];
+	unsigned char  misc_reg;
+	unsigned char  crtc_regs[25];
+	unsigned char  ar_regs[20];
+	unsigned char  gr_regs[9];
+} vga_mode_data_t;
+
+/* This contains the VGA Mode Table.  A ptr to this exists in the
+ * Environment. */
+extern vga_mode_data_t VB_CODE_SEG vga_mode_data[];
+
+/* This contains a pointer to the VGA Mode_Table.  This is necessary, so
+ * vga_mode.c can use this to program the mode, incase the user has
+ * changed the Environment Table. */
+extern vga_mode_data_t FAR (*vga_mode_data_ptr)[];
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/io.h b/drivers/gpu/drm/emgd/include/io.h
new file mode 100644
index 0000000..9b534df
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/io.h
@@ -0,0 +1,422 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: io.h
+ * $Revision: 1.8 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains Linux user-space implementations for the OAL io.h
+ *  abstractions.
+ *-----------------------------------------------------------------------------
+ */
+
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <config.h>
+#include <igd_debug.h>
+
+
+#ifndef _OAL_LINUX_KERNEL_IO_H
+#define _OAL_LINUX_KERNEL_IO_H
+
+extern unsigned long _os_read_port8(unsigned long port);
+extern void _os_write_port8(unsigned long port, unsigned char value);
+extern unsigned long _os_read_port16(unsigned long port);
+extern void _os_write_port16(unsigned long port, unsigned short value);
+extern unsigned long _os_read_port32(unsigned long port);
+extern void _os_write_port32(unsigned long port, unsigned long value);
+
+/*
+ * Debug macros rely on the existence of emgd_debug pointer. It is defined
+ * in the HAL. If an IAL wishes to use the print routines and is not
+ * linked with the HAL it will need to provide an emgd_debug pointer.
+ */
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#ifndef FAR
+#define FAR
+#endif
+
+
+/*
+ * All files including io.h should define MODULE_NAME to be a bit
+ * within the emgd_debug_t data structure. If MODULE_NAME is not defined
+ * debug printing will be controlled by the global "debug" bit rather
+ * than a per-module bit.
+ */
+#ifndef MODULE_NAME
+#define MODULE_NAME hal.debug
+#endif
+
+/*
+ * Debug Print Macros use os_get_funcname to get the name of the
+ * function they are in. They cannot rely on __func__ alone because
+ * the function name may be overridden by the caller.
+ *
+ * If the caller wants to override the printed function name they may
+ * call os_set_funcname prior to each call to EMGD_DEBUG/ERROR/TRACE.
+ */
+static const char *_os_override_funcname = NULL;
+
+static __inline int os_set_funcname( const char *name )
+{
+	_os_override_funcname = name;
+	return 1;
+}
+
+static __inline const char *os_get_funcname( const char *name )
+{
+	const char *ret;
+	ret = (_os_override_funcname)?_os_override_funcname:name;
+	_os_override_funcname = NULL;
+	return ret;
+}
+
+
+
+/*
+ * EMGD_ERROR()
+ * Printing with EMGD_ERROR will be compiled in to all debug drivers and
+ * removed from all production drivers. EMGD_ERROR printing is used for
+ * driver errors that should not happen under normal operation. As such,
+ * these messages cannot be disabled at runtime.
+ *
+ * All OAL implementations should result in EMGD_ERROR messsages in the
+ * following format:
+ * <OPTIONAL OS ERROR PREFIX> FUNCTION_NAME Message
+ *
+ * The FUNCTION_NAME must be obtained by calling
+ * os_get_funcname(__func__) to insure that any overridden function names
+ * are respected.
+ */
+#ifndef EMGD_ERROR
+#ifdef DEBUG_BUILD_TYPE
+#define EMGD_ERROR(...)							\
+  do {									\
+    printk(KERN_ERR "%s ERROR: ", __FUNCTION__);			\
+    printk(__VA_ARGS__);						\
+    printk("\n");							\
+    /*fflush(stderr);*/							\
+  } while(0);
+#else
+#define EMGD_ERROR(...)  do {} while(0)
+#endif
+#endif
+
+
+/* The CONFIG_USE_INFO_PRIORITY macro is #define'd in "config.h" */
+#ifdef CONFIG_USE_INFO_PRIORITY
+#define EMGD_DEBUG_MSG_PRIORITY KERN_INFO
+#else
+#define EMGD_DEBUG_MSG_PRIORITY KERN_DEBUG
+#endif
+
+/*
+ * EMGD_DEBUG()
+ * Printing with EMGD_DEBUG will be compiled in to all debug drivers and
+ * removed from all production drivers. EMGD_DEBUG printing is used for
+ * debug messages that give information useful for debugging problems.
+ * EMGD_DEBUG messages can be enabled/disabled at compile time and runtime
+ * on a per-module basis.
+ *
+ * Disabling/Enabling module bits in CONFIG_DEBUG_FLAGS will control the
+ *  default printing of debug messages.
+ * Disabling/Enabling the bit in emgd_debug->MODULE_NAME will control
+ *  the runtime printing of debug messages.
+ *
+ * All OAL implementations should result in EMGD_DEBUG messsages in the
+ * following format:
+ * <OPTIONAL OS PREFIX> function_name Message
+ *
+ * The FUNCTION_NAME must be obtained by calling
+ * os_get_funcname(__func__) to insure that any overridden function names
+ * are respected.
+ */
+#ifndef EMGD_DEBUG
+#ifdef DEBUG_BUILD_TYPE
+#define EMGD_DEBUG(...) if(emgd_debug &&emgd_debug-> MODULE_NAME)	\
+  do {													\
+    printk(EMGD_DEBUG_MSG_PRIORITY "[EMGD_DEBUG] %s ", __FUNCTION__);	\
+    printk(__VA_ARGS__);								\
+    printk("\n");										\
+    /*fflush(stdout);*/									\
+  } while(0);
+#else
+#define EMGD_DEBUG(...)  do {} while(0)
+#endif
+#endif
+
+/*
+ * EMGD_DEBUG_S()
+ * Printing with EMGD_DEBUG_S will be compiled in to all debug drivers and
+ * removed from all production drivers. EMGD_DEBUG_S printing is used for
+ * debug messages that give information useful for debugging problems in
+ * a shortened form (used by the HAL for multi-line prints).
+ * EMGD_DEBUG_S messages can be enabled/disabled at compile time and runtime
+ * on a per-module basis.
+ *
+ * Disabling/Enabling module bits in CONFIG_DEBUG_FLAGS will control the
+ *  default printing of debug messages.
+ * Disabling/Enabling the bit in emgd_debug->MODULE_NAME will control
+ *  the runtime printing of debug messages.
+ *
+ * All OAL implementations should result in EMGD_DEBUG_S messsages in the
+ * following format:
+ * <OPTIONAL OS PREFIX> Message
+ *
+ * The FUNCTION_NAME must be obtained by calling
+ * os_get_funcname(__func__) to insure that any overridden function names
+ * are respected.
+ */
+#ifndef EMGD_DEBUG_S
+#ifdef DEBUG_BUILD_TYPE
+#define EMGD_DEBUG_S(...) if(emgd_debug && emgd_debug-> MODULE_NAME) 	\
+  do {													\
+    printk(EMGD_DEBUG_MSG_PRIORITY __VA_ARGS__);			\
+    printk("\n");										\
+    /* fflush(stdout);*/								\
+  } while(0);
+#else
+#define EMGD_DEBUG_S(...)     do {} while(0)
+#endif
+#endif
+
+/*
+ * EMGD_TRACE_ENTER
+ * Tracing with EMGD_TRACE_ENTER will be compiled in to all debug drivers and
+ * removed from all production drivers. EMGD_TRACE_ENTER will print a fixed
+ * "Enter" message when entering a function.
+ * EMGD_TRACE_ENTER messages can be enabled/disabled at compile time and
+ * runtime on a per-module basis. To Enable tracing in a module, the Global
+ * emgd_debug->trace bit must be enabled as well as the per-module
+ * debug bit.
+ *
+ * Disabling/Enabling module bits in CONFIG_DEBUG_FLAGS will control the
+ *  default printing of debug messages.
+ * Disabling/Enabling the bit in emgd_debug->MODULE_NAME will control
+ *  the runtime printing of debug messages.
+ *
+ * All OAL implementations should result in EMGD_TRACE_ENTER messsages in the
+ * following format:
+ * <OPTIONAL OS PREFIX> function_name ENTER
+ */
+#ifndef EMGD_TRACE_ENTER
+#ifdef DEBUG_BUILD_TYPE
+#define EMGD_TRACE_ENTER if(emgd_debug && emgd_debug->hal.trace) EMGD_DEBUG("ENTER")
+#else
+#define EMGD_TRACE_ENTER
+#endif
+#endif
+
+/*
+ * EMGD_TRACE_EXIT
+ * Tracing with EMGD_TRACE_EXIT will be compiled in to all debug drivers and
+ * removed from all production drivers. EMGD_TRACE_EXIT will print a fixed
+ * "Exit" message when exiting a function without error.
+ * EMGD_TRACE_EXIT messages can be enabled/disabled at compile time and
+ * runtime on a per-module basis. To Enable tracing in a module, the Global
+ * emgd_debug->trace bit must be enabled as well as the per-module
+ * debug bit.
+ *
+ * Disabling/Enabling module bits in CONFIG_DEBUG_FLAGS will control the
+ *  default printing of debug messages.
+ * Disabling/Enabling the bit in emgd_debug->MODULE_NAME will control
+ *  the runtime printing of debug messages.
+ *
+ * All OAL implementations should result in EMGD_TRACE_EXIT messsages in the
+ * following format:
+ * <OPTIONAL OS PREFIX> function_name EXIT
+ */
+#ifndef EMGD_TRACE_EXIT
+#ifdef DEBUG_BUILD_TYPE
+#define EMGD_TRACE_EXIT if(emgd_debug && emgd_debug->hal.trace) EMGD_DEBUG("EXIT")
+#else
+#define EMGD_TRACE_EXIT
+#endif
+#endif
+
+/*
+ * EMGD_ERROR_EXIT()
+ * Tracing with EMGD_ERROR_EXIT will be compiled in to all debug drivers and
+ * removed from all production drivers. EMGD_ERROR_EXIT will print an error
+ * as well as a fixed "Exit" message when exiting a function without error.
+ * EMGD_ERROR_EXIT messages can be enabled/disabled at compile time and
+ * runtime on a per-module basis. To Enable tracing in a module, the Global
+ * emgd_debug->trace bit must be enabled as well as the per-module
+ * debug bit.
+ *
+ * Note: Only the Tracing message can be disabled, the error message will
+ * still print as with EMGD_ERROR().
+ *
+ * Disabling/Enabling module bits in CONFIG_DEBUG_FLAGS will control the
+ *  default printing of debug messages.
+ * Disabling/Enabling the bit in emgd_debug->MODULE_NAME will control
+ *  the runtime printing of debug messages.
+ *
+ * All OAL implementations should result in EMGD_ERROR_EXIT messsages in the
+ * following format:
+ * <OPTIONAL OS ERROR PREFIX> function_name EXIT Message
+ */
+#ifndef EMGD_ERROR_EXIT
+#ifdef DEBUG_BUILD_TYPE
+#define EMGD_ERROR_EXIT													\
+	if(emgd_debug && emgd_debug->hal.trace) EMGD_DEBUG("EXIT With Error..."); \
+	EMGD_ERROR
+#else
+#define EMGD_ERROR_EXIT(...)   do {} while(0)
+#endif
+#endif
+
+
+/*
+ * EMGD_VERBOSE()
+ * Verbose printing that is useful only when debugging specific problems
+ * or contains lots of text should be implemented in a single function and
+ * called from within the EMGD_VERBOSE macro. The default and runtime
+ * control of this output can be altered by changing the value of the
+ * global emgd_debug->verbose.
+ */
+#ifndef EMGD_VERBOSE
+#ifdef DEBUG_BUILD_TYPE
+#define EMGD_VERBOSE(opt, func) if(emgd_debug-> opt) func;
+#else
+#define EMGD_VERBOSE(opt, func)
+#endif
+#endif
+
+/*
+ * EMGD_ASSERT( Statement, Message, Error Code)
+ * EMGD_ASSERT should be used to verify the values of statements that
+ * should always be true. EMGD_ASSERT will generate code only in debug drivers
+ * and therefore should only be used for things that should never be false
+ * in production drivers. For example, testing for null parameters in
+ * an internal interface.
+ *
+ * Usage: EMGD_ASSERT(char_ptr, "Char Pointer is NULL", -IGD_ERROR_INVAL)
+ * Usage: EMGD_ASSERT(char_ptr, "Char Pointer is NULL", )
+ */
+#ifndef EMGD_ASSERT
+#ifdef EMGD_DEBUG
+#define EMGD_ASSERT(a, m, e) if(!(a)) { EMGD_ERROR_EXIT("ASSERT: " m); return e; }
+#else
+#define EMGD_ASSERT(a, m, e)
+#endif
+#endif
+
+/*
+ * This macro _may_ be defined by an OAL port to modify the mmio
+ * base address prior to use. Commonly this is used to make the base
+ * address 0 to remove code for vbios.
+ */
+#ifdef _EMGD_MMIO
+#define EMGD_MMIO(a) _EMGD_MMIO(a)
+#else
+#define EMGD_MMIO(a) a
+#endif
+
+
+
+#define EMGD_READ32(addr) *(volatile unsigned int *)(addr)
+#define EMGD_WRITE32(value, addr) \
+		(*(volatile unsigned long *)(addr) = (value))
+/*	EMGD_DEBUG ("EMGD_WRITE32: 0x%p=0x%lx\n", (addr), (value)); \*/
+
+#define EMGD_READ8(addr) *(volatile unsigned char *)(addr)
+#define EMGD_WRITE8(value, addr) \
+		(*(volatile unsigned char *)(addr) = (value))
+/*	EMGD_DEBUG ("EMGD_WRITE8: 0x%p=0x%x\n", (addr), (value));	\*/
+
+
+/* PORT IO Macros */
+#if 0
+// user mode.  To be removed.
+#define _EMGD_READ_PORT8(port)          _os_read_port8(port)
+#define _EMGD_WRITE_PORT8(port, value)  _os_write_port8(port, value)
+
+#define _EMGD_READ_PORT16(port)         _os_read_port16(port)
+#define _EMGD_WRITE_PORT16(port, value) _os_write_port16(port, value)
+
+#define _EMGD_READ_PORT32(port)         _os_read_port32(port)
+#define _EMGD_WRITE_PORT32(port, value) _os_write_port32(port, value)
+#else
+// Linux kernel mode port I/O
+#define EMGD_READ_PORT8(port)          inb(port)
+#define EMGD_WRITE_PORT8(port, value)  outb(value, port)
+
+#define EMGD_READ_PORT16(port)         inw(port)
+#define EMGD_WRITE_PORT16(port, value) outw(value, port)
+
+#define EMGD_READ_PORT32(port)         inl(port)
+#define EMGD_WRITE_PORT32(port, value) outl(value, port)
+#endif
+
+#ifdef DEBUG_MEM
+extern unsigned long global_virt_mmadr;
+extern unsigned long global_virt_mmadr_offset;
+
+static __inline *(volatile unsigned int *) _EMGD_READ32(unsigned int addr)
+{
+    if ((addr < 0x10100000) && (addr > 0x10000000)) {
+		return *(volatile unsigned int *)(addr+global_virt_mmadr-global_virt_mmadr_offset);
+	} else {
+		return *(volatile unsigned int *)(addr);
+    }
+}
+
+static __inline void _EMGD_WRITE32(unsigned int value, unsigned int addr) \
+{
+	if ((addr < 0x10100000) && (addr > 0x10000000)) {
+		*(volatile unsigned int *)(addr+global_virt_mmadr-global_virt_mmadr_offset) = value;
+	} else {
+		*(volatile unsigned int *)addr = value;
+	}
+	printf("EMGD_WRITE32: *0x%x = 0x%x\n", addr, value);
+}
+
+static __inline *(volatile unsigned char *) _EMGD_READ8(unsigned int addr)
+{
+    if ((addr < 0x10100000) && (addr > 0x10000000)) {
+		return *(volatile unsigned char *)(addr+global_virt_mmadr-global_virt_mmadr_offset);
+	} else {
+		return *(volatile unsigned char *)addr;
+	}
+}
+
+static __inline void _EMGD_WRITE8(unsigned char value, unsigned int addr) \
+{
+    if ((addr < 0x10100000) && (addr > 0x10000000)) {
+		(*(volatile unsigned char *)(addr+global_virt_mmadr-global_virt_mmadr_offset) = value);
+    } else {
+		(*(volatile unsigned char *)(addr) = value);
+    }
+    printf("EMGD_WRITE8: *0x%x = 0x%c\n", addr, value);
+}
+#endif /* DEBUG_MEM */
+
+#define EMGD_PTR_TO_ULONG(ptr) (ptr)
+#define EMGD_ULONG_TO_PTR(ulong) (ulong)
+
+#endif
diff --git a/drivers/gpu/drm/emgd/include/memmap.h b/drivers/gpu/drm/emgd/include/memmap.h
new file mode 100644
index 0000000..a02e943
--- /dev/null
+++ b/drivers/gpu/drm/emgd/include/memmap.h
@@ -0,0 +1,104 @@
+/*
+ *-----------------------------------------------------------------------------
+ * Filename: memmap.h
+ * $Revision: 1.6 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description:
+ *  This file contains OS abstractions for memory mapping of bus addresses.
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef _OAL_IO_MEMMAP_H
+#define _OAL_IO_MEMMAP_H
+
+void * os_map_io_to_mem_cache(
+        unsigned long base_address,
+        unsigned long size);
+void * os_map_io_to_mem_nocache(
+        unsigned long base_address,
+        unsigned long size);
+void os_unmap_io_from_mem(
+        void * virt_addr,
+        unsigned long size);
+
+
+/*****************************************************************************
+ * Function: os_map_io_to_mem_cache
+ *
+ * Description:
+ *  This function will reserve a range of virtual memory space of "size" and
+ *  map the that virtual address to the hardware "base_address" provided. This
+ *  function call will enable caching of read write transactions to the region.
+ * Parameters:
+ *              IN: base_address -> the base bus/hardware address that will be
+ *                                  used as the target of the memory mapping.
+ *              IN: size-> the size of the virtual memory range requested to
+ *                         be mapped
+ * Return Value:
+ *              NULL for failure OR
+ *              valid virtual address casted as a void *
+ *
+ ****************************************************************************/
+#define OS_MAP_IO_TO_MEM_CACHE(a, b)	os_map_io_to_mem_cache(a, b)
+
+/*****************************************************************************
+ * Function: os_map_io_to_mem_cache
+ *
+ * Description:
+ *  This function will reserve a range of virtual memory space of "size" and
+ *  map the that virtual address to the hardware "base_address" provided. This
+ *  function call will NOT cache any read/write transactions to the region and
+ *  apply the access directly to the hardware bus address that is mapped.
+ * Parameters:
+ *              IN: base_address -> the base bus/hardware address that will be
+ *                                  used as the target of the memory mapping.
+ *              IN: size-> the size of the virtual memory range requested to
+ *                         be mapped
+ * Return Value:
+ *              NULL for failure OR
+ *              valid virtual address casted as a void *
+ *
+ ****************************************************************************/
+#define OS_MAP_IO_TO_MEM_NOCACHE(a, b)	os_map_io_to_mem_nocache(a, b)
+#define OS_MAP_IO_TO_LARGE_MEM_NOCACHE(a, b) os_map_io_to_mem_nocache(a, b)
+
+/*****************************************************************************
+ * Function: os_map_io_to_mem_cache
+ *
+ * Description:
+ *  This function will unmap the range of virtual memory space of "size" that
+ *  was previously mapped with any of the above functions.
+ * Parameters:
+ *              IN: virt_address -> the base bus or hardware address that will
+ *                                  be used as the target of the memory
+ *                                  mapping.
+ *              IN: size-> the size of the virtual memory range as requested in
+ *                         os_map_io*
+ * Return Value:
+ *              none (N/A)
+ *
+ ****************************************************************************/
+#define OS_UNMAP_IO_FROM_MEM(a, b)	os_unmap_io_from_mem(a, b)
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/include4/dbgdrvif.h b/drivers/gpu/drm/emgd/pvr/include4/dbgdrvif.h
new file mode 100644
index 0000000..0527e7b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/dbgdrvif.h
@@ -0,0 +1,263 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _DBGDRVIF_
+#define _DBGDRVIF_
+
+
+#include "ioctldef.h"
+
+#define DEBUG_CAPMODE_FRAMED			0x00000001UL
+#define DEBUG_CAPMODE_CONTINUOUS		0x00000002UL
+#define DEBUG_CAPMODE_HOTKEY			0x00000004UL
+
+#define DEBUG_OUTMODE_STANDARDDBG		0x00000001UL
+#define DEBUG_OUTMODE_MONO				0x00000002UL
+#define DEBUG_OUTMODE_STREAMENABLE		0x00000004UL
+#define DEBUG_OUTMODE_ASYNC				0x00000008UL
+#define DEBUG_OUTMODE_SGXVGA            0x00000010UL
+
+#define DEBUG_FLAGS_USE_NONPAGED_MEM	0x00000001UL
+#define DEBUG_FLAGS_NO_BUF_EXPANDSION	0x00000002UL
+#define DEBUG_FLAGS_ENABLESAMPLE		0x00000004UL
+
+#define DEBUG_FLAGS_TEXTSTREAM			0x80000000UL
+
+#define DEBUG_LEVEL_0					0x00000001UL
+#define DEBUG_LEVEL_1					0x00000003UL
+#define DEBUG_LEVEL_2					0x00000007UL
+#define DEBUG_LEVEL_3					0x0000000FUL
+#define DEBUG_LEVEL_4					0x0000001FUL
+#define DEBUG_LEVEL_5					0x0000003FUL
+#define DEBUG_LEVEL_6					0x0000007FUL
+#define DEBUG_LEVEL_7					0x000000FFUL
+#define DEBUG_LEVEL_8					0x000001FFUL
+#define DEBUG_LEVEL_9					0x000003FFUL
+#define DEBUG_LEVEL_10					0x000007FFUL
+#define DEBUG_LEVEL_11					0x00000FFFUL
+
+#define DEBUG_LEVEL_SEL0				0x00000001UL
+#define DEBUG_LEVEL_SEL1				0x00000002UL
+#define DEBUG_LEVEL_SEL2				0x00000004UL
+#define DEBUG_LEVEL_SEL3				0x00000008UL
+#define DEBUG_LEVEL_SEL4				0x00000010UL
+#define DEBUG_LEVEL_SEL5				0x00000020UL
+#define DEBUG_LEVEL_SEL6				0x00000040UL
+#define DEBUG_LEVEL_SEL7				0x00000080UL
+#define DEBUG_LEVEL_SEL8				0x00000100UL
+#define DEBUG_LEVEL_SEL9				0x00000200UL
+#define DEBUG_LEVEL_SEL10				0x00000400UL
+#define DEBUG_LEVEL_SEL11				0x00000800UL
+
+#define DEBUG_SERVICE_IOCTL_BASE		0x800UL
+#define DEBUG_SERVICE_CREATESTREAM		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_DESTROYSTREAM		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETSTREAM			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITESTRING		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x04, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READSTRING		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x05, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITE				CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x06, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READ				CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x07, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGMODE		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x08, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGOUTMODE	CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x09, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGLEVEL		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0A, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETFRAME			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0B, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETFRAME			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0C, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_OVERRIDEMODE		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0D, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_DEFAULTMODE		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0E, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETSERVICETABLE	CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0F, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITE2			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x10, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITESTRINGCM		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x11, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITECM			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x12, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETMARKER			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x13, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETMARKER			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x14, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_ISCAPTUREFRAME	CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x15, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITELF			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x16, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READLF			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x17, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WAITFOREVENT		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x18, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+
+typedef enum _DBG_EVENT_
+{
+	DBG_EVENT_STREAM_DATA = 1
+} DBG_EVENT;
+
+typedef struct _DBG_IN_CREATESTREAM_
+{
+	IMG_UINT32 ui32Pages;
+	IMG_UINT32 ui32CapMode;
+	IMG_UINT32 ui32OutMode;
+	IMG_CHAR *pszName;
+}DBG_IN_CREATESTREAM, *PDBG_IN_CREATESTREAM;
+
+typedef struct _DBG_IN_FINDSTREAM_
+{
+	IMG_BOOL bResetStream;
+	IMG_CHAR *pszName;
+}DBG_IN_FINDSTREAM, *PDBG_IN_FINDSTREAM;
+
+typedef struct _DBG_IN_WRITESTRING_
+{
+	IMG_VOID *pvStream;
+	IMG_UINT32 ui32Level;
+	IMG_CHAR *pszString;
+}DBG_IN_WRITESTRING, *PDBG_IN_WRITESTRING;
+
+typedef struct _DBG_IN_READSTRING_
+{
+	IMG_VOID *pvStream;
+	IMG_UINT32 ui32StringLen;
+	IMG_CHAR *pszString;
+} DBG_IN_READSTRING, *PDBG_IN_READSTRING;
+
+typedef struct _DBG_IN_SETDEBUGMODE_
+{
+	IMG_VOID *pvStream;
+	IMG_UINT32 ui32Mode;
+	IMG_UINT32 ui32Start;
+	IMG_UINT32 ui32End;
+	IMG_UINT32 ui32SampleRate;
+} DBG_IN_SETDEBUGMODE, *PDBG_IN_SETDEBUGMODE;
+
+typedef struct _DBG_IN_SETDEBUGOUTMODE_
+{
+	IMG_VOID *pvStream;
+	IMG_UINT32 ui32Mode;
+} DBG_IN_SETDEBUGOUTMODE, *PDBG_IN_SETDEBUGOUTMODE;
+
+typedef struct _DBG_IN_SETDEBUGLEVEL_
+{
+	IMG_VOID *pvStream;
+	IMG_UINT32 ui32Level;
+} DBG_IN_SETDEBUGLEVEL, *PDBG_IN_SETDEBUGLEVEL;
+
+typedef struct _DBG_IN_SETFRAME_
+{
+	IMG_VOID *pvStream;
+	IMG_UINT32 ui32Frame;
+} DBG_IN_SETFRAME, *PDBG_IN_SETFRAME;
+
+typedef struct _DBG_IN_WRITE_
+{
+	IMG_VOID *pvStream;
+	IMG_UINT32 ui32Level;
+	IMG_UINT32 ui32TransferSize;
+	IMG_UINT8 *pui8InBuffer;
+} DBG_IN_WRITE, *PDBG_IN_WRITE;
+
+typedef struct _DBG_IN_READ_
+{
+	IMG_VOID *pvStream;
+	IMG_BOOL bReadInitBuffer;
+	IMG_UINT32 ui32OutBufferSize;
+	IMG_UINT8 *pui8OutBuffer;
+} DBG_IN_READ, *PDBG_IN_READ;
+
+typedef struct _DBG_IN_OVERRIDEMODE_
+{
+	IMG_VOID *pvStream;
+	IMG_UINT32 ui32Mode;
+} DBG_IN_OVERRIDEMODE, *PDBG_IN_OVERRIDEMODE;
+
+typedef struct _DBG_IN_ISCAPTUREFRAME_
+{
+	IMG_VOID *pvStream;
+	IMG_BOOL bCheckPreviousFrame;
+} DBG_IN_ISCAPTUREFRAME, *PDBG_IN_ISCAPTUREFRAME;
+
+typedef struct _DBG_IN_SETMARKER_
+{
+	IMG_VOID *pvStream;
+	IMG_UINT32 ui32Marker;
+} DBG_IN_SETMARKER, *PDBG_IN_SETMARKER;
+
+typedef struct _DBG_IN_WRITE_LF_
+{
+	IMG_UINT32 ui32Flags;
+	IMG_VOID *pvStream;
+	IMG_UINT32 ui32Level;
+	IMG_UINT32 ui32BufferSize;
+	IMG_UINT8 *pui8InBuffer;
+} DBG_IN_WRITE_LF, *PDBG_IN_WRITE_LF;
+
+#define WRITELF_FLAGS_RESETBUF		0x00000001UL
+
+typedef struct _DBG_STREAM_
+{
+	struct _DBG_STREAM_ *psNext;
+	struct _DBG_STREAM_ *psInitStream;
+	IMG_BOOL   bInitPhaseComplete;
+	IMG_UINT32 ui32Flags;
+	IMG_UINT32 ui32Base;
+	IMG_UINT32 ui32Size;
+	IMG_UINT32 ui32RPtr;
+	IMG_UINT32 ui32WPtr;
+	IMG_UINT32 ui32DataWritten;
+	IMG_UINT32 ui32CapMode;
+	IMG_UINT32 ui32OutMode;
+	IMG_UINT32 ui32DebugLevel;
+	IMG_UINT32 ui32DefaultMode;
+	IMG_UINT32 ui32Start;
+	IMG_UINT32 ui32End;
+	IMG_UINT32 ui32Current;
+	IMG_UINT32 ui32Access;
+	IMG_UINT32 ui32SampleRate;
+	IMG_UINT32 ui32Reserved;
+	IMG_UINT32 ui32Timeout;
+	IMG_UINT32 ui32Marker;
+	IMG_CHAR szName[30];
+} DBG_STREAM,*PDBG_STREAM;
+
+typedef struct _DBGKM_SERVICE_TABLE_
+{
+	IMG_UINT32 ui32Size;
+	IMG_VOID * 	(IMG_CALLCONV *pfnCreateStream)			(IMG_CHAR * pszName,IMG_UINT32 ui32CapMode,IMG_UINT32 ui32OutMode,IMG_UINT32 ui32Flags,IMG_UINT32 ui32Pages);
+	IMG_VOID 	(IMG_CALLCONV *pfnDestroyStream)		(PDBG_STREAM psStream);
+	IMG_VOID * 	(IMG_CALLCONV *pfnFindStream) 			(IMG_CHAR * pszName, IMG_BOOL bResetInitBuffer);
+	IMG_UINT32 	(IMG_CALLCONV *pfnWriteString) 			(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+	IMG_UINT32 	(IMG_CALLCONV *pfnReadString)			(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit);
+	IMG_UINT32 	(IMG_CALLCONV *pfnWriteBIN)				(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+	IMG_UINT32 	(IMG_CALLCONV *pfnReadBIN)				(PDBG_STREAM psStream,IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBufferSize,IMG_UINT8 *pui8OutBuf);
+	IMG_VOID 	(IMG_CALLCONV *pfnSetCaptureMode)		(PDBG_STREAM psStream,IMG_UINT32 ui32CapMode,IMG_UINT32 ui32Start,IMG_UINT32 ui32Stop,IMG_UINT32 ui32SampleRate);
+	IMG_VOID 	(IMG_CALLCONV *pfnSetOutputMode)		(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode);
+	IMG_VOID 	(IMG_CALLCONV *pfnSetDebugLevel)		(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel);
+	IMG_VOID 	(IMG_CALLCONV *pfnSetFrame)				(PDBG_STREAM psStream,IMG_UINT32 ui32Frame);
+	IMG_UINT32 	(IMG_CALLCONV *pfnGetFrame)				(PDBG_STREAM psStream);
+	IMG_VOID 	(IMG_CALLCONV *pfnOverrideMode)			(PDBG_STREAM psStream,IMG_UINT32 ui32Mode);
+	IMG_VOID 	(IMG_CALLCONV *pfnDefaultMode)			(PDBG_STREAM psStream);
+	IMG_UINT32	(IMG_CALLCONV *pfnDBGDrivWrite2)		(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+	IMG_UINT32 	(IMG_CALLCONV *pfnWriteStringCM)		(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+	IMG_UINT32	(IMG_CALLCONV *pfnWriteBINCM)			(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+	IMG_VOID 	(IMG_CALLCONV *pfnSetMarker)			(PDBG_STREAM psStream,IMG_UINT32 ui32Marker);
+	IMG_UINT32 	(IMG_CALLCONV *pfnGetMarker)			(PDBG_STREAM psStream);
+	IMG_VOID 	(IMG_CALLCONV *pfnStartInitPhase)		(PDBG_STREAM psStream);
+	IMG_VOID 	(IMG_CALLCONV *pfnStopInitPhase)		(PDBG_STREAM psStream);
+	IMG_BOOL 	(IMG_CALLCONV *pfnIsCaptureFrame)		(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame);
+	IMG_UINT32 	(IMG_CALLCONV *pfnWriteLF)				(PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags);
+	IMG_UINT32 	(IMG_CALLCONV *pfnReadLF)				(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 *pui8OutBuf);
+	IMG_UINT32 	(IMG_CALLCONV *pfnGetStreamOffset)		(PDBG_STREAM psStream);
+	IMG_VOID	(IMG_CALLCONV *pfnSetStreamOffset)		(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset);
+	IMG_BOOL 	(IMG_CALLCONV *pfnIsLastCaptureFrame)	(PDBG_STREAM psStream);
+	IMG_VOID 	(IMG_CALLCONV *pfnWaitForEvent)	(DBG_EVENT eEvent);
+} DBGKM_SERVICE_TABLE, *PDBGKM_SERVICE_TABLE;
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/include4/img_defs.h b/drivers/gpu/drm/emgd/pvr/include4/img_defs.h
new file mode 100644
index 0000000..454a68f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/img_defs.h
@@ -0,0 +1,104 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__IMG_DEFS_H__)
+#define __IMG_DEFS_H__
+
+#include "img_types.h"
+
+typedef		enum	img_tag_TriStateSwitch
+{
+	IMG_ON		=	0x00,
+	IMG_OFF,
+	IMG_IGNORE
+
+} img_TriStateSwitch, * img_pTriStateSwitch;
+
+#define		IMG_SUCCESS				0
+
+#define		IMG_NO_REG				1
+
+#if defined (NO_INLINE_FUNCS)
+	#define	INLINE
+	#define	FORCE_INLINE
+#else
+#if defined (__cplusplus)
+	#define INLINE					inline
+	#define	FORCE_INLINE			inline
+#else
+#if	!defined(INLINE)
+	#define	INLINE					__inline
+#endif
+	#define	FORCE_INLINE			static __inline
+#endif
+#endif
+
+
+#ifndef PVR_UNREFERENCED_PARAMETER
+#define	PVR_UNREFERENCED_PARAMETER(param) (param) = (param)
+#endif
+
+#ifdef __GNUC__
+#define unref__ __attribute__ ((unused))
+#else
+#define unref__
+#endif
+
+#ifndef _TCHAR_DEFINED
+#if defined(UNICODE)
+typedef unsigned short		TCHAR, *PTCHAR, *PTSTR;
+#else
+typedef char				TCHAR, *PTCHAR, *PTSTR;
+#endif
+#define _TCHAR_DEFINED
+#endif
+
+
+			#if defined(__linux__) || defined(__METAG)
+
+				#define IMG_CALLCONV
+				#define IMG_INTERNAL	__attribute__ ((visibility ("hidden")))
+				#define IMG_EXPORT
+				#define IMG_IMPORT
+				#define IMG_RESTRICT	__restrict__
+
+			#else
+					#error("define an OS")
+			#endif
+
+#ifndef IMG_ABORT
+	#define IMG_ABORT()	abort()
+#endif
+
+#ifndef IMG_MALLOC
+	#define IMG_MALLOC(A)		malloc	(A)
+#endif
+
+#ifndef IMG_FREE
+	#define IMG_FREE(A)			free	(A)
+#endif
+
+#define IMG_CONST const
+
+#define IMG_FORMAT_PRINTF(x,y)
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/include4/img_types.h b/drivers/gpu/drm/emgd/pvr/include4/img_types.h
new file mode 100644
index 0000000..a7b92e1
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/img_types.h
@@ -0,0 +1,124 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __IMG_TYPES_H__
+#define __IMG_TYPES_H__
+
+#if !defined(IMG_ADDRSPACE_CPUVADDR_BITS)
+#define IMG_ADDRSPACE_CPUVADDR_BITS		32
+#endif
+
+#if !defined(IMG_ADDRSPACE_PHYSADDR_BITS)
+#define IMG_ADDRSPACE_PHYSADDR_BITS		32
+#endif
+
+typedef unsigned int	IMG_UINT,	*IMG_PUINT;
+typedef signed int		IMG_INT,	*IMG_PINT;
+
+typedef unsigned char	IMG_UINT8,	*IMG_PUINT8;
+typedef unsigned char	IMG_BYTE,	*IMG_PBYTE;
+typedef signed char		IMG_INT8,	*IMG_PINT8;
+typedef char			IMG_CHAR,	*IMG_PCHAR;
+
+typedef unsigned short	IMG_UINT16,	*IMG_PUINT16;
+typedef signed short	IMG_INT16,	*IMG_PINT16;
+typedef unsigned long	IMG_UINT32,	*IMG_PUINT32;
+typedef signed long		IMG_INT32,	*IMG_PINT32;
+
+#if !defined(IMG_UINT32_MAX)
+	#define IMG_UINT32_MAX 0xFFFFFFFFUL
+#endif
+
+	#if (defined(LINUX) || defined(__METAG))
+#if !defined(USE_CODE)
+		typedef unsigned long long		IMG_UINT64,	*IMG_PUINT64;
+		typedef long long 				IMG_INT64,	*IMG_PINT64;
+#endif
+	#else
+
+		#error("define an OS")
+
+	#endif
+
+#if !(defined(LINUX) && defined (__KERNEL__))
+typedef float			IMG_FLOAT,	*IMG_PFLOAT;
+typedef double			IMG_DOUBLE, *IMG_PDOUBLE;
+#endif
+
+typedef	enum tag_img_bool
+{
+	IMG_FALSE		= 0,
+	IMG_TRUE		= 1,
+	IMG_FORCE_ALIGN = 0x7FFFFFFF
+} IMG_BOOL, *IMG_PBOOL;
+
+typedef void            IMG_VOID,	*IMG_PVOID;
+
+typedef IMG_INT32       IMG_RESULT;
+
+typedef IMG_UINT32      IMG_UINTPTR_T;
+
+typedef IMG_PVOID       IMG_HANDLE;
+
+typedef void**          IMG_HVOID,	* IMG_PHVOID;
+
+typedef IMG_UINT32		IMG_SIZE_T;
+
+#define IMG_NULL        0
+
+
+typedef IMG_PVOID IMG_CPU_VIRTADDR;
+
+typedef struct
+{
+
+	IMG_UINT32 uiAddr;
+#define IMG_CAST_TO_DEVVADDR_UINT(var)		(IMG_UINT32)(var)
+
+} IMG_DEV_VIRTADDR;
+
+typedef struct _IMG_CPU_PHYADDR
+{
+
+	IMG_UINTPTR_T uiAddr;
+} IMG_CPU_PHYADDR;
+
+typedef struct _IMG_DEV_PHYADDR
+{
+#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
+
+	IMG_UINTPTR_T uiAddr;
+#else
+	IMG_UINT32 uiAddr;
+	IMG_UINT32 uiHighAddr;
+#endif
+} IMG_DEV_PHYADDR;
+
+typedef struct _IMG_SYS_PHYADDR
+{
+
+	IMG_UINTPTR_T uiAddr;
+} IMG_SYS_PHYADDR;
+
+#include "img_defs.h"
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/include4/ioctldef.h b/drivers/gpu/drm/emgd/pvr/include4/ioctldef.h
new file mode 100644
index 0000000..d7e494a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/ioctldef.h
@@ -0,0 +1,94 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __IOCTLDEF_H__
+#define __IOCTLDEF_H__
+
+#define MAKEIOCTLINDEX(i)	(((i) >> 2) & 0xFFF)
+
+#ifndef CTL_CODE
+
+#define DEVICE_TYPE ULONG
+
+#define FILE_DEVICE_BEEP                0x00000001
+#define FILE_DEVICE_CD_ROM              0x00000002
+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM  0x00000003
+#define FILE_DEVICE_CONTROLLER          0x00000004
+#define FILE_DEVICE_DATALINK            0x00000005
+#define FILE_DEVICE_DFS                 0x00000006
+#define FILE_DEVICE_DISK                0x00000007
+#define FILE_DEVICE_DISK_FILE_SYSTEM    0x00000008
+#define FILE_DEVICE_FILE_SYSTEM         0x00000009
+#define FILE_DEVICE_INPORT_PORT         0x0000000a
+#define FILE_DEVICE_KEYBOARD            0x0000000b
+#define FILE_DEVICE_MAILSLOT            0x0000000c
+#define FILE_DEVICE_MIDI_IN             0x0000000d
+#define FILE_DEVICE_MIDI_OUT            0x0000000e
+#define FILE_DEVICE_MOUSE               0x0000000f
+#define FILE_DEVICE_MULTI_UNC_PROVIDER  0x00000010
+#define FILE_DEVICE_NAMED_PIPE          0x00000011
+#define FILE_DEVICE_NETWORK             0x00000012
+#define FILE_DEVICE_NETWORK_BROWSER     0x00000013
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
+#define FILE_DEVICE_NULL                0x00000015
+#define FILE_DEVICE_PARALLEL_PORT       0x00000016
+#define FILE_DEVICE_PHYSICAL_NETCARD    0x00000017
+#define FILE_DEVICE_PRINTER             0x00000018
+#define FILE_DEVICE_SCANNER             0x00000019
+#define FILE_DEVICE_SERIAL_MOUSE_PORT   0x0000001a
+#define FILE_DEVICE_SERIAL_PORT         0x0000001b
+#define FILE_DEVICE_SCREEN              0x0000001c
+#define FILE_DEVICE_SOUND               0x0000001d
+#define FILE_DEVICE_STREAMS             0x0000001e
+#define FILE_DEVICE_TAPE                0x0000001f
+#define FILE_DEVICE_TAPE_FILE_SYSTEM    0x00000020
+#define FILE_DEVICE_TRANSPORT           0x00000021
+#define FILE_DEVICE_UNKNOWN             0x00000022
+#define FILE_DEVICE_VIDEO               0x00000023
+#define FILE_DEVICE_VIRTUAL_DISK        0x00000024
+#define FILE_DEVICE_WAVE_IN             0x00000025
+#define FILE_DEVICE_WAVE_OUT            0x00000026
+#define FILE_DEVICE_8042_PORT           0x00000027
+#define FILE_DEVICE_NETWORK_REDIRECTOR  0x00000028
+#define FILE_DEVICE_BATTERY             0x00000029
+#define FILE_DEVICE_BUS_EXTENDER        0x0000002a
+#define FILE_DEVICE_MODEM               0x0000002b
+#define FILE_DEVICE_VDM                 0x0000002c
+#define FILE_DEVICE_MASS_STORAGE        0x0000002d
+
+#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
+    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+
+#define METHOD_BUFFERED                 0
+#define METHOD_IN_DIRECT                1
+#define METHOD_OUT_DIRECT               2
+#define METHOD_NEITHER                  3
+
+#define FILE_ANY_ACCESS                 0
+#define FILE_READ_ACCESS          ( 0x0001 )
+#define FILE_WRITE_ACCESS         ( 0x0002 )
+
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/include4/pdumpdefs.h b/drivers/gpu/drm/emgd/pvr/include4/pdumpdefs.h
new file mode 100644
index 0000000..6285c6d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/pdumpdefs.h
@@ -0,0 +1,95 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__PDUMPDEFS_H__)
+#define __PDUMPDEFS_H__
+
+typedef enum _PDUMP_PIXEL_FORMAT_
+{
+	PVRSRV_PDUMP_PIXEL_FORMAT_UNSUPPORTED = 0,
+	PVRSRV_PDUMP_PIXEL_FORMAT_RGB8 = 1,
+	PVRSRV_PDUMP_PIXEL_FORMAT_RGB332 = 2,
+	PVRSRV_PDUMP_PIXEL_FORMAT_KRGB555 = 3,
+	PVRSRV_PDUMP_PIXEL_FORMAT_RGB565 = 4,
+	PVRSRV_PDUMP_PIXEL_FORMAT_ARGB4444 = 5,
+	PVRSRV_PDUMP_PIXEL_FORMAT_ARGB1555 = 6,
+	PVRSRV_PDUMP_PIXEL_FORMAT_RGB888 = 7,
+	PVRSRV_PDUMP_PIXEL_FORMAT_ARGB8888 = 8,
+	PVRSRV_PDUMP_PIXEL_FORMAT_YUV8 = 9,
+	PVRSRV_PDUMP_PIXEL_FORMAT_AYUV4444 = 10,
+	PVRSRV_PDUMP_PIXEL_FORMAT_VY0UY1_8888 = 11,
+	PVRSRV_PDUMP_PIXEL_FORMAT_UY0VY1_8888 = 12,
+	PVRSRV_PDUMP_PIXEL_FORMAT_Y0UY1V_8888 = 13,
+	PVRSRV_PDUMP_PIXEL_FORMAT_Y0VY1U_8888 = 14,
+	PVRSRV_PDUMP_PIXEL_FORMAT_YUV888 = 15,
+	PVRSRV_PDUMP_PIXEL_FORMAT_UYVY10101010 = 16,
+	PVRSRV_PDUMP_PIXEL_FORMAT_VYAUYA8888 = 17,
+	PVRSRV_PDUMP_PIXEL_FORMAT_AYUV8888 = 18,
+	PVRSRV_PDUMP_PIXEL_FORMAT_AYUV2101010 = 19,
+	PVRSRV_PDUMP_PIXEL_FORMAT_YUV101010 = 20,
+	PVRSRV_PDUMP_PIXEL_FORMAT_PL12Y8 = 21,
+	PVRSRV_PDUMP_PIXEL_FORMAT_YUV_IMC2 = 22,
+	PVRSRV_PDUMP_PIXEL_FORMAT_YUV_YV12 = 23,
+	PVRSRV_PDUMP_PIXEL_FORMAT_YUV_PL8 = 24,
+	PVRSRV_PDUMP_PIXEL_FORMAT_YUV_PL12 = 25,
+	PVRSRV_PDUMP_PIXEL_FORMAT_422PL12YUV8 = 26,
+	PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV8 = 27,
+	PVRSRV_PDUMP_PIXEL_FORMAT_PL12Y10 = 28,
+	PVRSRV_PDUMP_PIXEL_FORMAT_422PL12YUV10 = 29,
+	PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV10 = 30,
+	PVRSRV_PDUMP_PIXEL_FORMAT_ABGR8888 = 31,
+	PVRSRV_PDUMP_PIXEL_FORMAT_BGRA8888 = 32,
+	PVRSRV_PDUMP_PIXEL_FORMAT_ARGB8332 = 33,
+	PVRSRV_PDUMP_PIXEL_FORMAT_RGB555 = 34,
+	PVRSRV_PDUMP_PIXEL_FORMAT_F16 = 35,
+	PVRSRV_PDUMP_PIXEL_FORMAT_F32 = 36,
+	PVRSRV_PDUMP_PIXEL_FORMAT_L16 = 37,
+	PVRSRV_PDUMP_PIXEL_FORMAT_L32 = 38,
+
+	PVRSRV_PDUMP_PIXEL_FORMAT_FORCE_I32 = 0x7fffffff
+
+} PDUMP_PIXEL_FORMAT;
+
+typedef enum _PDUMP_MEM_FORMAT_
+{
+	PVRSRV_PDUMP_MEM_FORMAT_STRIDE = 0,
+	PVRSRV_PDUMP_MEM_FORMAT_RESERVED = 1,
+	PVRSRV_PDUMP_MEM_FORMAT_TILED = 8,
+	PVRSRV_PDUMP_MEM_FORMAT_TWIDDLED = 9,
+	PVRSRV_PDUMP_MEM_FORMAT_HYBRID = 10,
+
+	PVRSRV_PDUMP_MEM_FORMAT_FORCE_I32 = 0x7fffffff
+} PDUMP_MEM_FORMAT;
+
+typedef enum _PDUMP_POLL_OPERATOR
+{
+	PDUMP_POLL_OPERATOR_EQUAL = 0,
+	PDUMP_POLL_OPERATOR_LESS = 1,
+	PDUMP_POLL_OPERATOR_LESSEQUAL = 2,
+	PDUMP_POLL_OPERATOR_GREATER = 3,
+	PDUMP_POLL_OPERATOR_GREATEREQUAL = 4,
+	PDUMP_POLL_OPERATOR_NOTEQUAL = 5,
+} PDUMP_POLL_OPERATOR;
+
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/include4/pvr_debug.h b/drivers/gpu/drm/emgd/pvr/include4/pvr_debug.h
new file mode 100644
index 0000000..8459841
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/pvr_debug.h
@@ -0,0 +1,123 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __PVR_DEBUG_H__
+#define __PVR_DEBUG_H__
+
+
+#include "img_types.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define PVR_MAX_DEBUG_MESSAGE_LEN	(512)
+
+#define DBGPRIV_FATAL		0x01UL
+#define DBGPRIV_ERROR		0x02UL
+#define DBGPRIV_WARNING		0x04UL
+#define DBGPRIV_MESSAGE		0x08UL
+#define DBGPRIV_VERBOSE		0x10UL
+#define DBGPRIV_CALLTRACE	0x20UL
+#define DBGPRIV_ALLOC		0x40UL
+#define DBGPRIV_ALLLEVELS	(DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING | DBGPRIV_MESSAGE | DBGPRIV_VERBOSE)
+
+
+
+#define PVR_DBG_FATAL		DBGPRIV_FATAL,__FILE__, __LINE__
+#define PVR_DBG_ERROR		DBGPRIV_ERROR,__FILE__, __LINE__
+#define PVR_DBG_WARNING		DBGPRIV_WARNING,__FILE__, __LINE__
+#define PVR_DBG_MESSAGE		DBGPRIV_MESSAGE,__FILE__, __LINE__
+#define PVR_DBG_VERBOSE		DBGPRIV_VERBOSE,__FILE__, __LINE__
+#define PVR_DBG_CALLTRACE	DBGPRIV_CALLTRACE,__FILE__, __LINE__
+#define PVR_DBG_ALLOC		DBGPRIV_ALLOC,__FILE__, __LINE__
+
+#if !defined(PVRSRV_NEED_PVR_ASSERT) && defined(DEBUG)
+#define PVRSRV_NEED_PVR_ASSERT
+#endif
+
+#if defined(PVRSRV_NEED_PVR_ASSERT) && !defined(PVRSRV_NEED_PVR_DPF)
+#define PVRSRV_NEED_PVR_DPF
+#endif
+
+#if !defined(PVRSRV_NEED_PVR_TRACE) && (defined(DEBUG) || defined(TIMING))
+#define PVRSRV_NEED_PVR_TRACE
+#endif
+
+
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+
+	#define PVR_ASSERT(EXPR) if (!(EXPR)) PVRSRVDebugAssertFail(__FILE__, __LINE__);
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
+													   IMG_UINT32 ui32Line);
+
+			#if defined(PVR_DBG_BREAK_ASSERT_FAIL)
+				#define PVR_DBG_BREAK	PVRSRVDebugAssertFail("PVR_DBG_BREAK", 0)
+			#else
+				#define PVR_DBG_BREAK
+			#endif
+
+#else
+
+	#define PVR_ASSERT(EXPR)
+	#define PVR_DBG_BREAK
+
+#endif
+
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+	#define PVR_DPF(X)		PVRSRVDebugPrintf X
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugPrintf(IMG_UINT32 ui32DebugLevel,
+												   const IMG_CHAR *pszFileName,
+												   IMG_UINT32 ui32Line,
+												   const IMG_CHAR *pszFormat,
+												   ...);
+
+#else
+
+	#define PVR_DPF(X)
+
+#endif
+
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+
+	#define PVR_TRACE(X)	PVRSRVTrace X
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVTrace(const IMG_CHAR* pszFormat, ... );
+
+#else
+
+	#define PVR_TRACE(X)
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/include4/pvrmodule.h b/drivers/gpu/drm/emgd/pvr/include4/pvrmodule.h
new file mode 100644
index 0000000..8aa4b20
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/pvrmodule.h
@@ -0,0 +1,27 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef	_PVRMODULE_H_
+#define	_PVRMODULE_H_
+MODULE_AUTHOR("Imagination Technologies Ltd. <gpl-support at imgtec.com>");
+MODULE_LICENSE("Dual MIT/GPL");
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/include4/pvrversion.h b/drivers/gpu/drm/emgd/pvr/include4/pvrversion.h
new file mode 100644
index 0000000..25bc19b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/pvrversion.h
@@ -0,0 +1,34 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _PVRVERSION_H_
+#define _PVRVERSION_H_
+
+#define PVRVERSION_MAJ 1
+#define PVRVERSION_MIN 5
+#define PVRVERSION_BRANCH 15
+#define PVRVERSION_BUILD 3226
+#define PVRVERSION_STRING "1.5.15.3226"
+#define PVRVERSION_FILE "eurasiacon.pj"
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/include4/regpaths.h b/drivers/gpu/drm/emgd/pvr/include4/regpaths.h
new file mode 100644
index 0000000..29a5574
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/regpaths.h
@@ -0,0 +1,39 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __REGPATHS_H__
+#define __REGPATHS_H__
+
+#define POWERVR_REG_ROOT 	   			"Drivers\\Display\\PowerVR"
+#define POWERVR_CHIP_KEY				"\\SGX1\\"
+
+#define POWERVR_EURASIA_KEY				"PowerVREurasia\\"
+
+#define POWERVR_SERVICES_KEY			"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\PowerVR\\"
+
+#define PVRSRV_REGISTRY_ROOT			POWERVR_EURASIA_KEY "HWSettings\\PVRSRVKM"
+
+
+#define MAX_REG_STRING_SIZE 128
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/include4/services.h b/drivers/gpu/drm/emgd/pvr/include4/services.h
new file mode 100644
index 0000000..0b8efbb
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/services.h
@@ -0,0 +1,866 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __SERVICES_H__
+#define __SERVICES_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "pdumpdefs.h"
+
+
+#define PVRSRV_4K_PAGE_SIZE		4096UL
+
+#define PVRSRV_MAX_CMD_SIZE		1024
+
+#define PVRSRV_MAX_DEVICES		16
+
+#define EVENTOBJNAME_MAXLENGTH (50)
+
+#define PVRSRV_MEM_READ						(1UL<<0)
+#define PVRSRV_MEM_WRITE					(1UL<<1)
+#define PVRSRV_MEM_CACHE_CONSISTENT			(1UL<<2)
+#define PVRSRV_MEM_NO_SYNCOBJ				(1UL<<3)
+#define PVRSRV_MEM_INTERLEAVED				(1UL<<4)
+#define PVRSRV_MEM_DUMMY					(1UL<<5)
+#define PVRSRV_MEM_EDM_PROTECT				(1UL<<6)
+#define PVRSRV_MEM_ZERO						(1UL<<7)
+#define PVRSRV_MEM_USER_SUPPLIED_DEVVADDR	(1UL<<8)
+#define PVRSRV_MEM_RAM_BACKED_ALLOCATION	(1UL<<9)
+#define PVRSRV_MEM_NO_RESMAN				(1UL<<10)
+#define PVRSRV_MEM_EXPORTED					(1UL<<11)
+
+
+#define PVRSRV_HAP_CACHED					(1UL<<12)
+#define PVRSRV_HAP_UNCACHED					(1UL<<13)
+#define PVRSRV_HAP_WRITECOMBINE				(1UL<<14)
+#define PVRSRV_HAP_CACHETYPE_MASK			(PVRSRV_HAP_CACHED|PVRSRV_HAP_UNCACHED|PVRSRV_HAP_WRITECOMBINE)
+#define PVRSRV_HAP_KERNEL_ONLY				(1UL<<15)
+#define PVRSRV_HAP_SINGLE_PROCESS			(1UL<<16)
+#define PVRSRV_HAP_MULTI_PROCESS			(1UL<<17)
+#define PVRSRV_HAP_FROM_EXISTING_PROCESS	(1UL<<18)
+#define PVRSRV_HAP_NO_CPU_VIRTUAL			(1UL<<19)
+#define PVRSRV_HAP_MAPTYPE_MASK				(PVRSRV_HAP_KERNEL_ONLY \
+                                            |PVRSRV_HAP_SINGLE_PROCESS \
+                                            |PVRSRV_HAP_MULTI_PROCESS \
+                                            |PVRSRV_HAP_FROM_EXISTING_PROCESS \
+                                            |PVRSRV_HAP_NO_CPU_VIRTUAL)
+
+#define PVRSRV_MEM_CACHED					PVRSRV_HAP_CACHED
+#define PVRSRV_MEM_UNCACHED					PVRSRV_HAP_UNCACHED
+#define PVRSRV_MEM_WRITECOMBINE				PVRSRV_HAP_WRITECOMBINE
+
+#define PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT	(24)
+
+#define PVRSRV_MAP_NOUSERVIRTUAL            (1UL<<27)
+
+#define PVRSRV_NO_CONTEXT_LOSS					0
+#define PVRSRV_SEVERE_LOSS_OF_CONTEXT			1
+#define PVRSRV_PRE_STATE_CHANGE_MASK			0x80
+
+
+#define PVRSRV_DEFAULT_DEV_COOKIE			(1)
+
+
+#define PVRSRV_MISC_INFO_TIMER_PRESENT				(1UL<<0)
+#define PVRSRV_MISC_INFO_CLOCKGATE_PRESENT			(1UL<<1)
+#define PVRSRV_MISC_INFO_MEMSTATS_PRESENT			(1UL<<2)
+#define PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT	(1UL<<3)
+#define PVRSRV_MISC_INFO_DDKVERSION_PRESENT			(1UL<<4)
+#define PVRSRV_MISC_INFO_CPUCACHEFLUSH_PRESENT		(1UL<<5)
+
+#define PVRSRV_MISC_INFO_RESET_PRESENT				(1UL<<31)
+
+#define PVRSRV_PDUMP_MAX_FILENAME_SIZE			20
+#define PVRSRV_PDUMP_MAX_COMMENT_SIZE			200
+
+
+#define PVRSRV_CHANGEDEVMEM_ATTRIBS_CACHECOHERENT		0x00000001
+
+#define PVRSRV_MAPEXTMEMORY_FLAGS_ALTERNATEVA			0x00000001
+#define PVRSRV_MAPEXTMEMORY_FLAGS_PHYSCONTIG			0x00000002
+
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC			0x00000001
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC			0x00000002
+
+typedef enum _PVRSRV_DEVICE_TYPE_
+{
+	PVRSRV_DEVICE_TYPE_UNKNOWN			= 0 ,
+	PVRSRV_DEVICE_TYPE_MBX1				= 1 ,
+	PVRSRV_DEVICE_TYPE_MBX1_LITE		= 2 ,
+
+	PVRSRV_DEVICE_TYPE_M24VA			= 3,
+	PVRSRV_DEVICE_TYPE_MVDA2			= 4,
+	PVRSRV_DEVICE_TYPE_MVED1			= 5,
+	PVRSRV_DEVICE_TYPE_MSVDX			= 6,
+
+	PVRSRV_DEVICE_TYPE_SGX				= 7,
+
+	PVRSRV_DEVICE_TYPE_VGX				= 8,
+
+
+	PVRSRV_DEVICE_TYPE_EXT				= 9,
+
+    PVRSRV_DEVICE_TYPE_LAST             = 9,
+
+	PVRSRV_DEVICE_TYPE_FORCE_I32		= 0x7fffffff
+
+} PVRSRV_DEVICE_TYPE;
+
+#define HEAP_ID( _dev_ , _dev_heap_idx_ )	(  ((_dev_)<<24) | ((_dev_heap_idx_)&((1<<24)-1))  )
+#define HEAP_IDX( _heap_id_ )				( (_heap_id_)&((1<<24) - 1 ) )
+#define HEAP_DEV( _heap_id_ )				( (_heap_id_)>>24 )
+
+#define PVRSRV_UNDEFINED_HEAP_ID			(~0LU)
+
+typedef enum
+{
+	IMG_EGL				= 0x00000001,
+	IMG_OPENGLES1		= 0x00000002,
+	IMG_OPENGLES2		= 0x00000003,
+	IMG_D3DM			= 0x00000004,
+	IMG_SRV_UM			= 0x00000005,
+	IMG_OPENVG			= 0x00000006,
+	IMG_SRVCLIENT		= 0x00000007,
+	IMG_VISTAKMD		= 0x00000008,
+	IMG_VISTA3DNODE		= 0x00000009,
+	IMG_VISTAMVIDEONODE	= 0x0000000A,
+	IMG_VISTAVPBNODE	= 0x0000000B,
+	IMG_OPENGL			= 0x0000000C,
+	IMG_D3D				= 0x0000000D,
+#if defined(SUPPORT_GRAPHICS_HAL)
+	IMG_GRAPHICS_HAL	= 0x0000000E
+#endif
+
+} IMG_MODULE_ID;
+
+
+#define APPHINT_MAX_STRING_SIZE	256
+
+typedef enum
+{
+	IMG_STRING_TYPE		= 1,
+	IMG_FLOAT_TYPE		,
+	IMG_UINT_TYPE		,
+	IMG_INT_TYPE		,
+	IMG_FLAG_TYPE
+}IMG_DATA_TYPE;
+
+
+typedef struct _PVRSRV_DEV_DATA_ *PPVRSRV_DEV_DATA;
+
+typedef struct _PVRSRV_DEVICE_IDENTIFIER_
+{
+	PVRSRV_DEVICE_TYPE		eDeviceType;
+	PVRSRV_DEVICE_CLASS		eDeviceClass;
+	IMG_UINT32				ui32DeviceIndex;
+
+} PVRSRV_DEVICE_IDENTIFIER;
+
+
+typedef struct _PVRSRV_CLIENT_DEV_DATA_
+{
+	IMG_UINT32		ui32NumDevices;
+	PVRSRV_DEVICE_IDENTIFIER asDevID[PVRSRV_MAX_DEVICES];
+	PVRSRV_ERROR	(*apfnDevConnect[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA);
+	PVRSRV_ERROR	(*apfnDumpTrace[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA);
+
+} PVRSRV_CLIENT_DEV_DATA;
+
+
+typedef struct _PVRSRV_CONNECTION_
+{
+	IMG_HANDLE hServices;
+	IMG_UINT32 ui32ProcessID;
+	PVRSRV_CLIENT_DEV_DATA	sClientDevData;
+}PVRSRV_CONNECTION;
+
+
+typedef struct _PVRSRV_DEV_DATA_
+{
+	PVRSRV_CONNECTION	sConnection;
+	IMG_HANDLE			hDevCookie;
+
+} PVRSRV_DEV_DATA;
+
+typedef struct _PVRSRV_MEMUPDATE_
+{
+	IMG_UINT32			ui32UpdateAddr;
+	IMG_UINT32			ui32UpdateVal;
+} PVRSRV_MEMUPDATE;
+
+typedef struct _PVRSRV_HWREG_
+{
+	IMG_UINT32			ui32RegAddr;
+	IMG_UINT32			ui32RegVal;
+} PVRSRV_HWREG;
+
+typedef struct _PVRSRV_MEMBLK_
+{
+	IMG_DEV_VIRTADDR	sDevVirtAddr;
+	IMG_HANDLE			hOSMemHandle;
+	IMG_HANDLE			hOSWrapMem;
+	IMG_HANDLE			hBuffer;
+	IMG_HANDLE			hResItem;
+	IMG_SYS_PHYADDR	 	*psIntSysPAddr;
+
+} PVRSRV_MEMBLK;
+
+typedef struct _PVRSRV_KERNEL_MEM_INFO_ *PPVRSRV_KERNEL_MEM_INFO;
+
+typedef struct _PVRSRV_CLIENT_MEM_INFO_
+{
+
+	IMG_PVOID				pvLinAddr;
+
+
+	IMG_PVOID				pvLinAddrKM;
+
+
+	IMG_DEV_VIRTADDR		sDevVAddr;
+
+
+
+
+
+
+	IMG_CPU_PHYADDR			sCpuPAddr;
+
+
+	IMG_UINT32				ui32Flags;
+
+
+
+
+	IMG_UINT32				ui32ClientFlags;
+
+
+	IMG_SIZE_T				ui32AllocSize;
+
+
+
+	struct _PVRSRV_CLIENT_SYNC_INFO_	*psClientSyncInfo;
+
+
+	IMG_HANDLE							hMappingInfo;
+
+
+	IMG_HANDLE							hKernelMemInfo;
+
+
+	IMG_HANDLE							hResItem;
+
+#if defined(SUPPORT_MEMINFO_IDS)
+	#if !defined(USE_CODE)
+
+	IMG_UINT64							ui64Stamp;
+	#else
+	IMG_UINT32							dummy1;
+	IMG_UINT32							dummy2;
+	#endif
+#endif
+
+	IMG_HANDLE							hOSMapInfo;
+
+	struct _PVRSRV_CLIENT_MEM_INFO_		*psNext;
+
+} PVRSRV_CLIENT_MEM_INFO, *PPVRSRV_CLIENT_MEM_INFO;
+
+
+#define PVRSRV_MAX_CLIENT_HEAPS (32)
+typedef struct _PVRSRV_HEAP_INFO_
+{
+	IMG_UINT32			ui32HeapID;
+	IMG_HANDLE 			hDevMemHeap;
+	IMG_DEV_VIRTADDR	sDevVAddrBase;
+	IMG_UINT32			ui32HeapByteSize;
+	IMG_UINT32			ui32Attribs;
+}PVRSRV_HEAP_INFO;
+
+
+
+
+typedef struct _PVRSRV_EVENTOBJECT_
+{
+
+	IMG_CHAR	szName[EVENTOBJNAME_MAXLENGTH];
+
+	IMG_HANDLE	hOSEventKM;
+
+} PVRSRV_EVENTOBJECT;
+
+typedef struct _PVRSRV_MISC_INFO_
+{
+	IMG_UINT32	ui32StateRequest;
+	IMG_UINT32	ui32StatePresent;
+
+
+	IMG_VOID	*pvSOCTimerRegisterKM;
+	IMG_VOID	*pvSOCTimerRegisterUM;
+	IMG_HANDLE	hSOCTimerRegisterOSMemHandle;
+	IMG_HANDLE	hSOCTimerRegisterMappingInfo;
+
+
+	IMG_VOID	*pvSOCClockGateRegs;
+	IMG_UINT32	ui32SOCClockGateRegsSize;
+
+
+	IMG_CHAR	*pszMemoryStr;
+	IMG_UINT32	ui32MemoryStrLen;
+
+
+	PVRSRV_EVENTOBJECT	sGlobalEventObject;
+	IMG_HANDLE			hOSGlobalEvent;
+
+
+	IMG_UINT32	aui32DDKVersion[4];
+
+
+
+	IMG_BOOL	bCPUCacheFlushAll;
+
+	IMG_BOOL	bDeferCPUCacheFlush;
+
+	IMG_PVOID	pvRangeAddrStart;
+
+	IMG_PVOID	pvRangeAddrEnd;
+
+} PVRSRV_MISC_INFO;
+
+
+typedef enum _PVRSRV_CLIENT_EVENT_
+{
+	PVRSRV_CLIENT_EVENT_HWTIMEOUT = 0,
+} PVRSRV_CLIENT_EVENT;
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVClientEvent(IMG_CONST PVRSRV_CLIENT_EVENT eEvent,
+											PVRSRV_DEV_DATA *psDevData,
+											IMG_PVOID pvData);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVConnect(PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDisconnect(PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevices(IMG_CONST PVRSRV_CONNECTION 			*psConnection,
+													IMG_UINT32 					*puiNumDevices,
+													PVRSRV_DEVICE_IDENTIFIER 	*puiDevIDs);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceData(IMG_CONST PVRSRV_CONNECTION 	*psConnection,
+													IMG_UINT32			uiDevIndex,
+													PVRSRV_DEV_DATA		*psDevData,
+													PVRSRV_DEVICE_TYPE	eDeviceType);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfo (IMG_CONST PVRSRV_CONNECTION *psConnection, PVRSRV_MISC_INFO *psMiscInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReleaseMiscInfo (IMG_CONST PVRSRV_CONNECTION *psConnection, PVRSRV_MISC_INFO *psMiscInfo);
+
+#if 1
+IMG_IMPORT
+IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+
+IMG_IMPORT
+IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
+
+IMG_IMPORT IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVPollForValue ( const PVRSRV_CONNECTION *psConnection,
+							IMG_HANDLE hOSEvent,
+							volatile IMG_UINT32 *pui32LinMemAddr,
+							IMG_UINT32 ui32Value,
+							IMG_UINT32 ui32Mask,
+							IMG_UINT32 ui32Waitus,
+							IMG_UINT32 ui32Tries);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContext(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+											IMG_HANDLE *phDevMemContext,
+											IMG_UINT32 *pui32SharedHeapCount,
+											PVRSRV_HEAP_INFO *psHeapInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContext(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+											IMG_HANDLE 			hDevMemContext);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfo(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+											IMG_HANDLE hDevMemContext,
+											IMG_UINT32 *pui32SharedHeapCount,
+											PVRSRV_HEAP_INFO *psHeapInfo);
+
+#if defined(PVRSRV_LOG_MEMORY_ALLOCS)
+	#define PVRSRVAllocDeviceMem_log(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo, logStr) \
+		(PVR_TRACE(("PVRSRVAllocDeviceMem(" #psDevData "," #hDevMemHeap "," #ui32Attribs "," #ui32Size "," #ui32Alignment "," #ppsMemInfo ")" \
+			": " logStr " (size = 0x%lx)", ui32Size)), \
+		PVRSRVAllocDeviceMem(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo))
+#else
+	#define PVRSRVAllocDeviceMem_log(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo, logStr) \
+		PVRSRVAllocDeviceMem(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo)
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocDeviceMem(IMG_CONST PVRSRV_DEV_DATA	*psDevData,
+									IMG_HANDLE		hDevMemHeap,
+									IMG_UINT32		ui32Attribs,
+									IMG_SIZE_T		ui32Size,
+									IMG_SIZE_T		ui32Alignment,
+									PVRSRV_CLIENT_MEM_INFO	**ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMem(IMG_CONST PVRSRV_DEV_DATA	*psDevData,
+								PVRSRV_CLIENT_MEM_INFO		*psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVExportDeviceMem(IMG_CONST PVRSRV_DEV_DATA	*psDevData,
+												PVRSRV_CLIENT_MEM_INFO		*psMemInfo,
+												IMG_HANDLE					*phMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReserveDeviceVirtualMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+											IMG_HANDLE			hDevMemHeap,
+											IMG_DEV_VIRTADDR	*psDevVAddr,
+											IMG_SIZE_T			ui32Size,
+											IMG_SIZE_T			ui32Alignment,
+											PVRSRV_CLIENT_MEM_INFO		**ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceVirtualMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+													PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+									IMG_HANDLE hKernelMemInfo,
+									IMG_HANDLE hDstDevMemHeap,
+									PVRSRV_CLIENT_MEM_INFO **ppsDstMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+										PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapExtMemory (IMG_CONST PVRSRV_DEV_DATA	*psDevData,
+									PVRSRV_CLIENT_MEM_INFO		*psMemInfo,
+									IMG_SYS_PHYADDR				*psSysPAddr,
+									IMG_UINT32					ui32Flags);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapExtMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+									PVRSRV_CLIENT_MEM_INFO		*psMemInfo,
+									IMG_UINT32					ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemory2(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+												IMG_HANDLE				hDevMemContext,
+												IMG_SIZE_T 				ui32ByteSize,
+												IMG_SIZE_T				ui32PageOffset,
+												IMG_BOOL				bPhysContig,
+												IMG_SYS_PHYADDR	 		*psSysPAddr,
+												IMG_VOID 				*pvLinAddr,
+												IMG_UINT32				ui32Flags,
+												PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemory(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+												IMG_HANDLE				hDevMemContext,
+												IMG_SIZE_T 				ui32ByteSize,
+												IMG_SIZE_T				ui32PageOffset,
+												IMG_BOOL				bPhysContig,
+												IMG_SYS_PHYADDR	 		*psSysPAddr,
+												IMG_VOID 				*pvLinAddr,
+												PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+												PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+PVRSRV_ERROR PVRSRVChangeDeviceMemoryAttributes(IMG_CONST PVRSRV_DEV_DATA			*psDevData,
+												PVRSRV_CLIENT_MEM_INFO	*psClientMemInfo,
+												IMG_UINT32				ui32Attribs);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+										IMG_HANDLE hDevMemContext,
+										IMG_HANDLE hDeviceClassBuffer,
+										PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+										PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapPhysToUserSpace(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+									  IMG_SYS_PHYADDR sSysPhysAddr,
+									  IMG_UINT32 uiSizeInBytes,
+									  IMG_PVOID *ppvUserAddr,
+									  IMG_UINT32 *puiActualSize,
+									  IMG_PVOID *ppvProcess);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapPhysToUserSpace(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+										IMG_PVOID pvUserAddr,
+										IMG_PVOID pvProcess);
+
+typedef enum _PVRSRV_SYNCVAL_MODE_
+{
+	PVRSRV_SYNCVAL_READ				= IMG_TRUE,
+	PVRSRV_SYNCVAL_WRITE			= IMG_FALSE,
+
+} PVRSRV_SYNCVAL_MODE, *PPVRSRV_SYNCVAL_MODE;
+
+typedef IMG_UINT32 PVRSRV_SYNCVAL;
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVWaitForOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+	PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVWaitForAllOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+	PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+	PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestAllOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+	PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestOpsNotComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+	PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestAllOpsNotComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+	PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT PVRSRV_SYNCVAL PVRSRVGetPendingOpSyncVal(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+	PVRSRV_SYNCVAL_MODE eMode);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDeviceClass(IMG_CONST PVRSRV_CONNECTION *psConnection,
+													PVRSRV_DEVICE_CLASS DeviceClass,
+													IMG_UINT32 *pui32DevCount,
+													IMG_UINT32 *pui32DevID);
+
+IMG_IMPORT
+IMG_HANDLE IMG_CALLCONV PVRSRVOpenDCDevice(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+											IMG_UINT32 ui32DeviceID);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCloseDCDevice(IMG_CONST PVRSRV_CONNECTION	*psConnection, IMG_HANDLE hDevice);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumDCFormats (IMG_HANDLE hDevice,
+											IMG_UINT32		*pui32Count,
+											DISPLAY_FORMAT	*psFormat);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumDCDims (IMG_HANDLE hDevice,
+										IMG_UINT32 		*pui32Count,
+										DISPLAY_FORMAT	*psFormat,
+										DISPLAY_DIMS	*psDims);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCSystemBuffer(IMG_HANDLE hDevice,
+										IMG_HANDLE *phBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCInfo(IMG_HANDLE hDevice,
+										DISPLAY_INFO* psDisplayInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDCSwapChain (IMG_HANDLE				hDevice,
+													IMG_UINT32				ui32Flags,
+													DISPLAY_SURF_ATTRIBUTES	*psDstSurfAttrib,
+													DISPLAY_SURF_ATTRIBUTES	*psSrcSurfAttrib,
+													IMG_UINT32				ui32BufferCount,
+													IMG_UINT32				ui32OEMFlags,
+													IMG_UINT32				*pui32SwapChainID,
+													IMG_HANDLE				*phSwapChain);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDCSwapChain (IMG_HANDLE hDevice,
+											IMG_HANDLE		hSwapChain);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCDstRect (IMG_HANDLE hDevice,
+										IMG_HANDLE	hSwapChain,
+										IMG_RECT	*psDstRect);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCSrcRect (IMG_HANDLE hDevice,
+										IMG_HANDLE	hSwapChain,
+										IMG_RECT	*psSrcRect);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCDstColourKey (IMG_HANDLE hDevice,
+											IMG_HANDLE	hSwapChain,
+											IMG_UINT32	ui32CKColour);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCSrcColourKey (IMG_HANDLE hDevice,
+											IMG_HANDLE	hSwapChain,
+											IMG_UINT32	ui32CKColour);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCBuffers(IMG_HANDLE hDevice,
+									IMG_HANDLE hSwapChain,
+									IMG_HANDLE *phBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCBuffer (IMG_HANDLE hDevice,
+										IMG_HANDLE hBuffer,
+										IMG_UINT32 ui32ClipRectCount,
+										IMG_RECT *psClipRect,
+										IMG_UINT32 ui32SwapInterval,
+										IMG_HANDLE hPrivateTag);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCSystem (IMG_HANDLE hDevice,
+										IMG_HANDLE hSwapChain);
+
+
+IMG_IMPORT
+IMG_HANDLE IMG_CALLCONV PVRSRVOpenBCDevice(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+											IMG_UINT32 ui32DeviceID);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCloseBCDevice(IMG_CONST PVRSRV_CONNECTION *psConnection,
+												IMG_HANDLE hDevice);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetBCBufferInfo(IMG_HANDLE hDevice,
+												BUFFER_INFO	*psBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetBCBuffer(IMG_HANDLE hDevice,
+												IMG_UINT32 ui32BufferIndex,
+												IMG_HANDLE *phBuffer);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpInit(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpStartInitPhase(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpStopInitPhase(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMemPol(IMG_CONST PVRSRV_CONNECTION *psConnection,
+										  PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+										  IMG_UINT32 ui32Offset,
+										  IMG_UINT32 ui32Value,
+										  IMG_UINT32 ui32Mask,
+										  IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSyncPol(IMG_CONST PVRSRV_CONNECTION *psConnection,
+										  PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+										  IMG_BOOL bIsRead,
+										  IMG_UINT32 ui32Value,
+										  IMG_UINT32 ui32Mask);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMem(IMG_CONST PVRSRV_CONNECTION *psConnection,
+									IMG_PVOID pvAltLinAddr,
+									PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+									IMG_UINT32 ui32Offset,
+									IMG_UINT32 ui32Bytes,
+									IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSync(IMG_CONST PVRSRV_CONNECTION *psConnection,
+										IMG_PVOID pvAltLinAddr,
+										PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+										IMG_UINT32 ui32Offset,
+										IMG_UINT32 ui32Bytes);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpReg(IMG_CONST PVRSRV_CONNECTION *psConnection,
+											IMG_UINT32 ui32RegAddr,
+											IMG_UINT32 ui32RegValue,
+											IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegPolWithFlags(IMG_CONST PVRSRV_CONNECTION *psConnection,
+													 IMG_UINT32 ui32RegAddr,
+													 IMG_UINT32 ui32RegValue,
+													 IMG_UINT32 ui32Mask,
+													 IMG_UINT32 ui32Flags);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegPol(IMG_CONST PVRSRV_CONNECTION *psConnection,
+											IMG_UINT32 ui32RegAddr,
+											IMG_UINT32 ui32RegValue,
+											IMG_UINT32 ui32Mask);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpPDReg(IMG_CONST PVRSRV_CONNECTION *psConnection,
+											IMG_UINT32 ui32RegAddr,
+											IMG_UINT32 ui32RegValue);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpPDDevPAddr(IMG_CONST PVRSRV_CONNECTION *psConnection,
+												PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+												IMG_UINT32 ui32Offset,
+												IMG_DEV_PHYADDR sPDDevPAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMemPages(IMG_CONST PVRSRV_CONNECTION *psConnection,
+												IMG_HANDLE			hKernelMemInfo,
+												IMG_DEV_PHYADDR		*pPages,
+												IMG_UINT32			ui32NumPages,
+												IMG_DEV_VIRTADDR	sDevAddr,
+												IMG_UINT32			ui32Start,
+												IMG_UINT32			ui32Length,
+												IMG_BOOL			bContinuous);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSetFrame(IMG_CONST PVRSRV_CONNECTION *psConnection,
+											  IMG_UINT32 ui32Frame);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpComment(IMG_CONST PVRSRV_CONNECTION *psConnection,
+											 IMG_CONST IMG_CHAR *pszComment,
+											 IMG_BOOL bContinuous);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCommentf(IMG_CONST PVRSRV_CONNECTION *psConnection,
+											  IMG_BOOL bContinuous,
+											  IMG_CONST IMG_CHAR *pszFormat, ...);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCommentWithFlagsf(IMG_CONST PVRSRV_CONNECTION *psConnection,
+													   IMG_UINT32 ui32Flags,
+													   IMG_CONST IMG_CHAR *pszFormat, ...);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpDriverInfo(IMG_CONST PVRSRV_CONNECTION *psConnection,
+								 				IMG_CHAR *pszString,
+												IMG_BOOL bContinuous);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpIsCapturing(IMG_CONST PVRSRV_CONNECTION *psConnection,
+								 				IMG_BOOL *pbIsCapturing);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpBitmap(IMG_CONST PVRSRV_CONNECTION *psConnection,
+								 			IMG_CHAR *pszFileName,
+											IMG_UINT32 ui32FileOffset,
+											IMG_UINT32 ui32Width,
+											IMG_UINT32 ui32Height,
+											IMG_UINT32 ui32StrideInBytes,
+											IMG_DEV_VIRTADDR sDevBaseAddr,
+											IMG_UINT32 ui32Size,
+											PDUMP_PIXEL_FORMAT ePixelFormat,
+											PDUMP_MEM_FORMAT eMemFormat,
+											IMG_UINT32 ui32PDumpFlags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegRead(IMG_CONST PVRSRV_CONNECTION *psConnection,
+								 			IMG_CONST IMG_CHAR *pszFileName,
+											IMG_UINT32 ui32FileOffset,
+											IMG_UINT32 ui32Address,
+											IMG_UINT32 ui32Size,
+											IMG_UINT32 ui32PDumpFlags);
+
+
+IMG_IMPORT
+IMG_BOOL IMG_CALLCONV PVRSRVPDumpIsCapturingTest(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCycleCountRegRead(IMG_CONST PVRSRV_CONNECTION *psConnection,
+														IMG_UINT32 ui32RegOffset,
+														IMG_BOOL bLastFrame);
+
+IMG_IMPORT IMG_HANDLE	PVRSRVLoadLibrary(const IMG_CHAR *pszLibraryName);
+IMG_IMPORT PVRSRV_ERROR	PVRSRVUnloadLibrary(IMG_HANDLE hExtDrv);
+IMG_IMPORT PVRSRV_ERROR	PVRSRVGetLibFuncAddr(IMG_HANDLE hExtDrv, const IMG_CHAR *pszFunctionName, IMG_VOID **ppvFuncAddr);
+
+IMG_IMPORT IMG_UINT32 PVRSRVClockus (void);
+IMG_IMPORT IMG_VOID PVRSRVWaitus (IMG_UINT32 ui32Timeus);
+IMG_IMPORT IMG_VOID PVRSRVReleaseThreadQuanta (void);
+IMG_IMPORT IMG_UINT32 IMG_CALLCONV PVRSRVGetCurrentProcessID(void);
+IMG_IMPORT IMG_CHAR * IMG_CALLCONV PVRSRVSetLocale(const IMG_CHAR *pszLocale);
+
+
+
+
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVCreateAppHintState(IMG_MODULE_ID eModuleID,
+														const IMG_CHAR *pszAppName,
+														IMG_VOID **ppvState);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVFreeAppHintState(IMG_MODULE_ID eModuleID,
+										 IMG_VOID *pvHintState);
+
+IMG_IMPORT IMG_BOOL IMG_CALLCONV PVRSRVGetAppHint(IMG_VOID			*pvHintState,
+												  const IMG_CHAR	*pszHintName,
+												  IMG_DATA_TYPE		eDataType,
+												  const IMG_VOID	*pvDefault,
+												  IMG_VOID			*pvReturn);
+
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVAllocUserModeMem (IMG_SIZE_T ui32Size);
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVCallocUserModeMem (IMG_SIZE_T ui32Size);
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVReallocUserModeMem (IMG_PVOID pvBase, IMG_SIZE_T uNewSize);
+IMG_IMPORT IMG_VOID  IMG_CALLCONV PVRSRVFreeUserModeMem (IMG_PVOID pvMem);
+IMG_IMPORT IMG_VOID PVRSRVMemCopy(IMG_VOID *pvDst, const IMG_VOID *pvSrc, IMG_SIZE_T ui32Size);
+IMG_IMPORT IMG_VOID PVRSRVMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T ui32Size);
+
+struct _PVRSRV_MUTEX_OPAQUE_STRUCT_;
+typedef	struct  _PVRSRV_MUTEX_OPAQUE_STRUCT_ *PVRSRV_MUTEX_HANDLE;
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateMutex(PVRSRV_MUTEX_HANDLE *phMutex);
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyMutex(PVRSRV_MUTEX_HANDLE hMutex);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockMutex(PVRSRV_MUTEX_HANDLE hMutex);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockMutex(PVRSRV_MUTEX_HANDLE hMutex);
+
+#if (defined(DEBUG) && defined(__linux__))
+IMG_PVOID PVRSRVAllocUserModeMemTracking(IMG_SIZE_T ui32Size, IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+IMG_PVOID PVRSRVCallocUserModeMemTracking(IMG_SIZE_T ui32Size, IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+IMG_VOID  PVRSRVFreeUserModeMemTracking(IMG_VOID *pvMem);
+IMG_PVOID PVRSRVReallocUserModeMemTracking(IMG_VOID *pvMem, IMG_SIZE_T ui32NewSize, IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+#endif
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVEventObjectWait(const PVRSRV_CONNECTION *psConnection,
+									IMG_HANDLE hOSEvent);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVModifyPendingSyncOps(PVRSRV_CONNECTION *psConnection,
+													  IMG_HANDLE hKernelSyncInfo,
+													  IMG_UINT32 ui32ModifyFlags,
+													  IMG_UINT32 *pui32ReadOpsPending,
+													  IMG_UINT32 *pui32WriteOpsPending);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVModifyCompleteSyncOps(PVRSRV_CONNECTION *psConnection,
+													  IMG_HANDLE hKernelSyncInfo,
+													  IMG_UINT32 ui32ModifyFlags);
+
+
+#define TIME_NOT_PASSED_UINT32(a,b,c)		((a - b) < c)
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/include4/servicesext.h b/drivers/gpu/drm/emgd/pvr/include4/servicesext.h
new file mode 100644
index 0000000..0f3dc1d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/servicesext.h
@@ -0,0 +1,647 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__SERVICESEXT_H__)
+#define __SERVICESEXT_H__
+
+#define PVRSRV_LOCKFLG_READONLY     	(1)
+
+typedef enum _PVRSRV_ERROR_
+{
+	PVRSRV_OK								=  0,
+	PVRSRV_ERROR_GENERIC					=  1,
+	PVRSRV_ERROR_OUT_OF_MEMORY				=  2,
+	PVRSRV_ERROR_TOO_FEW_BUFFERS			=  3,
+	PVRSRV_ERROR_SYMBOL_NOT_FOUND			=  4,
+	PVRSRV_ERROR_OUT_OF_HSPACE				=  5,
+	PVRSRV_ERROR_INVALID_PARAMS				=  6,
+	PVRSRV_ERROR_TILE_MAP_FAILED			=  7,
+	PVRSRV_ERROR_INIT_FAILURE				=  8,
+	PVRSRV_ERROR_CANT_REGISTER_CALLBACK 	=  9,
+	PVRSRV_ERROR_INVALID_DEVICE				= 10,
+	PVRSRV_ERROR_NOT_OWNER					= 11,
+	PVRSRV_ERROR_BAD_MAPPING				= 12,
+	PVRSRV_ERROR_TIMEOUT					= 13,
+	PVRSRV_ERROR_NO_PRIMARY					= 14,
+	PVRSRV_ERROR_FLIP_CHAIN_EXISTS			= 15,
+	PVRSRV_ERROR_CANNOT_ACQUIRE_SYSDATA 	= 16,
+	PVRSRV_ERROR_SCENE_INVALID				= 17,
+	PVRSRV_ERROR_STREAM_ERROR				= 18,
+	PVRSRV_ERROR_INVALID_INTERRUPT      	= 19,
+	PVRSRV_ERROR_FAILED_DEPENDENCIES		= 20,
+	PVRSRV_ERROR_CMD_NOT_PROCESSED			= 21,
+	PVRSRV_ERROR_CMD_TOO_BIG				= 22,
+	PVRSRV_ERROR_DEVICE_REGISTER_FAILED 	= 23,
+	PVRSRV_ERROR_FIFO_SPACE					= 24,
+	PVRSRV_ERROR_TA_RECOVERY				= 25,
+	PVRSRV_ERROR_INDOSORLOWPOWER			= 26,
+	PVRSRV_ERROR_TOOMANYBUFFERS				= 27,
+	PVRSRV_ERROR_NOT_SUPPORTED				= 28,
+	PVRSRV_ERROR_PROCESSING_BLOCKED			= 29,
+
+
+	PVRSRV_ERROR_CANNOT_FLUSH_QUEUE			= 31,
+	PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE		= 32,
+	PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS	= 33,
+	PVRSRV_ERROR_RETRY						= 34,
+
+	PVRSRV_ERROR_DDK_VERSION_MISMATCH		= 35,
+	PVRSRV_ERROR_BUILD_MISMATCH				= 36,
+	PVRSRV_ERROR_PDUMP_BUF_OVERFLOW,
+
+	PVRSRV_ERROR_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_ERROR;
+
+
+typedef enum _PVRSRV_DEVICE_CLASS_
+{
+	PVRSRV_DEVICE_CLASS_3D				= 0 ,
+	PVRSRV_DEVICE_CLASS_DISPLAY			= 1 ,
+	PVRSRV_DEVICE_CLASS_BUFFER			= 2 ,
+	PVRSRV_DEVICE_CLASS_VIDEO			= 3 ,
+
+	PVRSRV_DEVICE_CLASS_FORCE_I32 		= 0x7fffffff
+
+} PVRSRV_DEVICE_CLASS;
+
+
+
+typedef enum _PVRSRV_SYS_POWER_STATE_
+{
+	PVRSRV_SYS_POWER_STATE_Unspecified		= -1,
+	PVRSRV_SYS_POWER_STATE_D0				= 0,
+	PVRSRV_SYS_POWER_STATE_D1				= 1,
+	PVRSRV_SYS_POWER_STATE_D2				= 2,
+	PVRSRV_SYS_POWER_STATE_D3				= 3,
+	PVRSRV_SYS_POWER_STATE_D4				= 4,
+
+	PVRSRV_SYS_POWER_STATE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_SYS_POWER_STATE, *PPVRSRV_SYS_POWER_STATE;
+
+
+typedef enum _PVRSRV_DEV_POWER_STATE_
+{
+	PVRSRV_DEV_POWER_STATE_DEFAULT	= -1,
+	PVRSRV_DEV_POWER_STATE_ON		= 0,
+	PVRSRV_DEV_POWER_STATE_IDLE		= 1,
+	PVRSRV_DEV_POWER_STATE_OFF		= 2,
+
+	PVRSRV_DEV_POWER_STATE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_DEV_POWER_STATE, *PPVRSRV_DEV_POWER_STATE;
+
+
+typedef PVRSRV_ERROR (*PFN_PRE_POWER) (IMG_HANDLE				hDevHandle,
+									   PVRSRV_DEV_POWER_STATE	eNewPowerState,
+									   PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+typedef PVRSRV_ERROR (*PFN_POST_POWER) (IMG_HANDLE				hDevHandle,
+										PVRSRV_DEV_POWER_STATE	eNewPowerState,
+										PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+
+typedef PVRSRV_ERROR (*PFN_PRE_CLOCKSPEED_CHANGE) (IMG_HANDLE				hDevHandle,
+												   IMG_BOOL					bIdleDevice,
+												   PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+typedef PVRSRV_ERROR (*PFN_POST_CLOCKSPEED_CHANGE) (IMG_HANDLE				hDevHandle,
+													IMG_BOOL				bIdleDevice,
+													PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+
+
+typedef enum _PVRSRV_PIXEL_FORMAT_ {
+
+	PVRSRV_PIXEL_FORMAT_UNKNOWN			=  0,
+	PVRSRV_PIXEL_FORMAT_RGB565			=  1,
+	PVRSRV_PIXEL_FORMAT_RGB555			=  2,
+	PVRSRV_PIXEL_FORMAT_RGB888			=  3,
+	PVRSRV_PIXEL_FORMAT_BGR888			=  4,
+	PVRSRV_PIXEL_FORMAT_GREY_SCALE		=  8,
+	PVRSRV_PIXEL_FORMAT_PAL12			= 13,
+	PVRSRV_PIXEL_FORMAT_PAL8			= 14,
+	PVRSRV_PIXEL_FORMAT_PAL4			= 15,
+	PVRSRV_PIXEL_FORMAT_PAL2			= 16,
+	PVRSRV_PIXEL_FORMAT_PAL1			= 17,
+	PVRSRV_PIXEL_FORMAT_ARGB1555		= 18,
+	PVRSRV_PIXEL_FORMAT_ARGB4444		= 19,
+	PVRSRV_PIXEL_FORMAT_ARGB8888		= 20,
+	PVRSRV_PIXEL_FORMAT_ABGR8888		= 21,
+	PVRSRV_PIXEL_FORMAT_YV12			= 22,
+	PVRSRV_PIXEL_FORMAT_I420			= 23,
+    PVRSRV_PIXEL_FORMAT_IMC2            = 25,
+	PVRSRV_PIXEL_FORMAT_XRGB8888        = 26,
+	PVRSRV_PIXEL_FORMAT_XBGR8888,
+	PVRSRV_PIXEL_FORMAT_BGRA8888,
+	PVRSRV_PIXEL_FORMAT_XRGB4444,
+	PVRSRV_PIXEL_FORMAT_ARGB8332,
+	PVRSRV_PIXEL_FORMAT_A2RGB10,
+	PVRSRV_PIXEL_FORMAT_A2BGR10,
+	PVRSRV_PIXEL_FORMAT_P8,
+	PVRSRV_PIXEL_FORMAT_L8,
+	PVRSRV_PIXEL_FORMAT_A8L8,
+	PVRSRV_PIXEL_FORMAT_A4L4,
+	PVRSRV_PIXEL_FORMAT_L16,
+	PVRSRV_PIXEL_FORMAT_L6V5U5,
+	PVRSRV_PIXEL_FORMAT_V8U8,
+	PVRSRV_PIXEL_FORMAT_V16U16,
+	PVRSRV_PIXEL_FORMAT_QWVU8888,
+	PVRSRV_PIXEL_FORMAT_XLVU8888,
+	PVRSRV_PIXEL_FORMAT_QWVU16,
+	PVRSRV_PIXEL_FORMAT_D16,
+	PVRSRV_PIXEL_FORMAT_D24S8,
+	PVRSRV_PIXEL_FORMAT_D24X8,
+
+
+	PVRSRV_PIXEL_FORMAT_ABGR16,
+	PVRSRV_PIXEL_FORMAT_ABGR16F,
+	PVRSRV_PIXEL_FORMAT_ABGR32,
+	PVRSRV_PIXEL_FORMAT_ABGR32F,
+	PVRSRV_PIXEL_FORMAT_B10GR11,
+	PVRSRV_PIXEL_FORMAT_GR88,
+	PVRSRV_PIXEL_FORMAT_BGR32,
+	PVRSRV_PIXEL_FORMAT_GR32,
+	PVRSRV_PIXEL_FORMAT_E5BGR9,
+
+
+	PVRSRV_PIXEL_FORMAT_DUMMY1,
+	PVRSRV_PIXEL_FORMAT_DUMMY2,
+	PVRSRV_PIXEL_FORMAT_DUMMY3,
+	PVRSRV_PIXEL_FORMAT_DUMMY4,
+	PVRSRV_PIXEL_FORMAT_DUMMY5,
+
+
+	PVRSRV_PIXEL_FORMAT_R8G8_B8G8,
+	PVRSRV_PIXEL_FORMAT_G8R8_G8B8,
+
+
+	PVRSRV_PIXEL_FORMAT_NV11,
+	PVRSRV_PIXEL_FORMAT_NV12,
+
+
+	PVRSRV_PIXEL_FORMAT_YUY2,
+	PVRSRV_PIXEL_FORMAT_YUV420,
+	PVRSRV_PIXEL_FORMAT_YUV444,
+	PVRSRV_PIXEL_FORMAT_VUY444,
+	PVRSRV_PIXEL_FORMAT_YUYV,
+	PVRSRV_PIXEL_FORMAT_YVYU,
+	PVRSRV_PIXEL_FORMAT_UYVY,
+	PVRSRV_PIXEL_FORMAT_VYUY,
+
+	PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY,
+	PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YUYV,
+	PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YVYU,
+	PVRSRV_PIXEL_FORMAT_FOURCC_ORG_VYUY,
+	PVRSRV_PIXEL_FORMAT_FOURCC_ORG_AYUV,
+
+
+	PVRSRV_PIXEL_FORMAT_A32B32G32R32,
+	PVRSRV_PIXEL_FORMAT_A32B32G32R32F,
+	PVRSRV_PIXEL_FORMAT_A32B32G32R32_UINT,
+	PVRSRV_PIXEL_FORMAT_A32B32G32R32_SINT,
+
+
+	PVRSRV_PIXEL_FORMAT_B32G32R32,
+	PVRSRV_PIXEL_FORMAT_B32G32R32F,
+	PVRSRV_PIXEL_FORMAT_B32G32R32_UINT,
+	PVRSRV_PIXEL_FORMAT_B32G32R32_SINT,
+
+
+	PVRSRV_PIXEL_FORMAT_G32R32,
+	PVRSRV_PIXEL_FORMAT_G32R32F,
+	PVRSRV_PIXEL_FORMAT_G32R32_UINT,
+	PVRSRV_PIXEL_FORMAT_G32R32_SINT,
+
+
+	PVRSRV_PIXEL_FORMAT_D32F,
+	PVRSRV_PIXEL_FORMAT_R32,
+	PVRSRV_PIXEL_FORMAT_R32F,
+	PVRSRV_PIXEL_FORMAT_R32_UINT,
+	PVRSRV_PIXEL_FORMAT_R32_SINT,
+
+
+	PVRSRV_PIXEL_FORMAT_A16B16G16R16,
+	PVRSRV_PIXEL_FORMAT_A16B16G16R16F,
+	PVRSRV_PIXEL_FORMAT_A16B16G16R16_SINT,
+	PVRSRV_PIXEL_FORMAT_A16B16G16R16_SNORM,
+	PVRSRV_PIXEL_FORMAT_A16B16G16R16_UINT,
+	PVRSRV_PIXEL_FORMAT_A16B16G16R16_UNORM,
+
+
+	PVRSRV_PIXEL_FORMAT_G16R16,
+	PVRSRV_PIXEL_FORMAT_G16R16F,
+	PVRSRV_PIXEL_FORMAT_G16R16_UINT,
+	PVRSRV_PIXEL_FORMAT_G16R16_UNORM,
+	PVRSRV_PIXEL_FORMAT_G16R16_SINT,
+	PVRSRV_PIXEL_FORMAT_G16R16_SNORM,
+
+
+	PVRSRV_PIXEL_FORMAT_R16,
+	PVRSRV_PIXEL_FORMAT_R16F,
+	PVRSRV_PIXEL_FORMAT_R16_UINT,
+	PVRSRV_PIXEL_FORMAT_R16_UNORM,
+	PVRSRV_PIXEL_FORMAT_R16_SINT,
+	PVRSRV_PIXEL_FORMAT_R16_SNORM,
+
+
+	PVRSRV_PIXEL_FORMAT_X8R8G8B8,
+	PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM,
+	PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM_SRGB,
+
+	PVRSRV_PIXEL_FORMAT_A8R8G8B8,
+	PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM,
+	PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM_SRGB,
+
+	PVRSRV_PIXEL_FORMAT_A8B8G8R8,
+	PVRSRV_PIXEL_FORMAT_A8B8G8R8_UINT,
+	PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM,
+	PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM_SRGB,
+	PVRSRV_PIXEL_FORMAT_A8B8G8R8_SINT,
+	PVRSRV_PIXEL_FORMAT_A8B8G8R8_SNORM,
+
+
+	PVRSRV_PIXEL_FORMAT_G8R8,
+	PVRSRV_PIXEL_FORMAT_G8R8_UINT,
+	PVRSRV_PIXEL_FORMAT_G8R8_UNORM,
+	PVRSRV_PIXEL_FORMAT_G8R8_SINT,
+	PVRSRV_PIXEL_FORMAT_G8R8_SNORM,
+
+
+	PVRSRV_PIXEL_FORMAT_A8,
+	PVRSRV_PIXEL_FORMAT_R8,
+	PVRSRV_PIXEL_FORMAT_R8_UINT,
+	PVRSRV_PIXEL_FORMAT_R8_UNORM,
+	PVRSRV_PIXEL_FORMAT_R8_SINT,
+	PVRSRV_PIXEL_FORMAT_R8_SNORM,
+
+
+	PVRSRV_PIXEL_FORMAT_A2B10G10R10,
+	PVRSRV_PIXEL_FORMAT_A2B10G10R10_UNORM,
+	PVRSRV_PIXEL_FORMAT_A2B10G10R10_UINT,
+
+
+	PVRSRV_PIXEL_FORMAT_B10G11R11,
+	PVRSRV_PIXEL_FORMAT_B10G11R11F,
+
+
+	PVRSRV_PIXEL_FORMAT_X24G8R32,
+	PVRSRV_PIXEL_FORMAT_G8R24,
+	PVRSRV_PIXEL_FORMAT_X8R24,
+	PVRSRV_PIXEL_FORMAT_E5B9G9R9,
+	PVRSRV_PIXEL_FORMAT_R1,
+
+	PVRSRV_PIXEL_FORMAT_DUMMY6,
+	PVRSRV_PIXEL_FORMAT_DUMMY7,
+	PVRSRV_PIXEL_FORMAT_DUMMY8,
+	PVRSRV_PIXEL_FORMAT_DUMMY9,
+	PVRSRV_PIXEL_FORMAT_DUMMY10,
+	PVRSRV_PIXEL_FORMAT_DUMMY11,
+	PVRSRV_PIXEL_FORMAT_DUMMY12,
+	PVRSRV_PIXEL_FORMAT_DUMMY13,
+	PVRSRV_PIXEL_FORMAT_DUMMY14,
+	PVRSRV_PIXEL_FORMAT_DUMMY15,
+	PVRSRV_PIXEL_FORMAT_DUMMY16,
+	PVRSRV_PIXEL_FORMAT_DUMMY17,
+	PVRSRV_PIXEL_FORMAT_DUMMY18,
+	PVRSRV_PIXEL_FORMAT_DUMMY19,
+	PVRSRV_PIXEL_FORMAT_DUMMY20,
+
+
+	PVRSRV_PIXEL_FORMAT_L_F16,
+	PVRSRV_PIXEL_FORMAT_L_F16_REP,
+	PVRSRV_PIXEL_FORMAT_L_F16_A_F16,
+	PVRSRV_PIXEL_FORMAT_A_F16,
+	PVRSRV_PIXEL_FORMAT_B16G16R16F,
+
+	PVRSRV_PIXEL_FORMAT_L_F32,
+	PVRSRV_PIXEL_FORMAT_A_F32,
+	PVRSRV_PIXEL_FORMAT_L_F32_A_F32,
+
+
+	PVRSRV_PIXEL_FORMAT_PVRTC2,
+	PVRSRV_PIXEL_FORMAT_PVRTC4,
+	PVRSRV_PIXEL_FORMAT_PVRTCII2,
+	PVRSRV_PIXEL_FORMAT_PVRTCII4,
+	PVRSRV_PIXEL_FORMAT_PVRTCIII,
+	PVRSRV_PIXEL_FORMAT_PVRO8,
+	PVRSRV_PIXEL_FORMAT_PVRO88,
+	PVRSRV_PIXEL_FORMAT_PT1,
+	PVRSRV_PIXEL_FORMAT_PT2,
+	PVRSRV_PIXEL_FORMAT_PT4,
+	PVRSRV_PIXEL_FORMAT_PT8,
+	PVRSRV_PIXEL_FORMAT_PTW,
+	PVRSRV_PIXEL_FORMAT_PTB,
+	PVRSRV_PIXEL_FORMAT_MONO8,
+	PVRSRV_PIXEL_FORMAT_MONO16,
+
+
+	PVRSRV_PIXEL_FORMAT_C0_YUYV,
+	PVRSRV_PIXEL_FORMAT_C0_UYVY,
+	PVRSRV_PIXEL_FORMAT_C0_YVYU,
+	PVRSRV_PIXEL_FORMAT_C0_VYUY,
+	PVRSRV_PIXEL_FORMAT_C1_YUYV,
+	PVRSRV_PIXEL_FORMAT_C1_UYVY,
+	PVRSRV_PIXEL_FORMAT_C1_YVYU,
+	PVRSRV_PIXEL_FORMAT_C1_VYUY,
+
+
+	PVRSRV_PIXEL_FORMAT_C0_YUV420_2P_UV,
+	PVRSRV_PIXEL_FORMAT_C0_YUV420_2P_VU,
+	PVRSRV_PIXEL_FORMAT_C0_YUV420_3P,
+	PVRSRV_PIXEL_FORMAT_C1_YUV420_2P_UV,
+	PVRSRV_PIXEL_FORMAT_C1_YUV420_2P_VU,
+	PVRSRV_PIXEL_FORMAT_C1_YUV420_3P,
+
+	PVRSRV_PIXEL_FORMAT_A2B10G10R10F,
+	PVRSRV_PIXEL_FORMAT_B8G8R8_SINT,
+	PVRSRV_PIXEL_FORMAT_PVRF32SIGNMASK,
+
+	PVRSRV_PIXEL_FORMAT_FORCE_I32 = 0x7fffffff,
+} PVRSRV_PIXEL_FORMAT;
+
+typedef enum _PVRSRV_ALPHA_FORMAT_ {
+	PVRSRV_ALPHA_FORMAT_UNKNOWN		=  0x00000000,
+	PVRSRV_ALPHA_FORMAT_PRE			=  0x00000001,
+	PVRSRV_ALPHA_FORMAT_NONPRE		=  0x00000002,
+	PVRSRV_ALPHA_FORMAT_MASK		=  0x0000000F,
+} PVRSRV_ALPHA_FORMAT;
+
+typedef enum _PVRSRV_COLOURSPACE_FORMAT_ {
+	PVRSRV_COLOURSPACE_FORMAT_UNKNOWN		=  0x00000000,
+	PVRSRV_COLOURSPACE_FORMAT_LINEAR		=  0x00010000,
+	PVRSRV_COLOURSPACE_FORMAT_NONLINEAR		=  0x00020000,
+	PVRSRV_COLOURSPACE_FORMAT_MASK			=  0x000F0000,
+} PVRSRV_COLOURSPACE_FORMAT;
+
+
+typedef enum _PVRSRV_ROTATION_ {
+	PVRSRV_ROTATE_0		=	0,
+	PVRSRV_ROTATE_90	=	1,
+	PVRSRV_ROTATE_180	=	2,
+	PVRSRV_ROTATE_270	=	3,
+	PVRSRV_FLIP_Y
+
+} PVRSRV_ROTATION;
+
+#define PVRSRV_CREATE_SWAPCHAIN_SHARED		(1<<0)
+#define PVRSRV_CREATE_SWAPCHAIN_QUERY		(1<<1)
+#define PVRSRV_CREATE_SWAPCHAIN_OEMOVERLAY	(1<<2)
+
+typedef struct _PVRSRV_SYNC_DATA_
+{
+
+	IMG_UINT32					ui32WriteOpsPending;
+	volatile IMG_UINT32			ui32WriteOpsComplete;
+
+
+	IMG_UINT32					ui32ReadOpsPending;
+	volatile IMG_UINT32			ui32ReadOpsComplete;
+
+
+	IMG_UINT32					ui32LastOpDumpVal;
+	IMG_UINT32					ui32LastReadOpDumpVal;
+
+} PVRSRV_SYNC_DATA;
+
+typedef struct _PVRSRV_CLIENT_SYNC_INFO_
+{
+
+	PVRSRV_SYNC_DATA			*psSyncData;
+
+
+
+
+
+	IMG_DEV_VIRTADDR		sWriteOpsCompleteDevVAddr;
+
+
+	IMG_DEV_VIRTADDR		sReadOpsCompleteDevVAddr;
+
+
+	IMG_HANDLE					hMappingInfo;
+
+
+	IMG_HANDLE					hKernelSyncInfo;
+
+} PVRSRV_CLIENT_SYNC_INFO, *PPVRSRV_CLIENT_SYNC_INFO;
+
+
+typedef struct PVRSRV_RESOURCE_TAG
+{
+	volatile IMG_UINT32 ui32Lock;
+	IMG_UINT32 			ui32ID;
+}PVRSRV_RESOURCE;
+typedef PVRSRV_RESOURCE PVRSRV_RES_HANDLE;
+
+
+typedef IMG_VOID (*PFN_CMD_COMPLETE) (IMG_HANDLE);
+typedef IMG_VOID (**PPFN_CMD_COMPLETE) (IMG_HANDLE);
+
+typedef IMG_BOOL (*PFN_CMD_PROC) (IMG_HANDLE, IMG_UINT32, IMG_VOID*);
+typedef IMG_BOOL (**PPFN_CMD_PROC) (IMG_HANDLE, IMG_UINT32, IMG_VOID*);
+
+
+typedef struct _IMG_RECT_
+{
+	IMG_INT32	x0;
+	IMG_INT32	y0;
+	IMG_INT32	x1;
+	IMG_INT32	y1;
+}IMG_RECT;
+
+typedef struct _IMG_RECT_16_
+{
+	IMG_INT16	x0;
+	IMG_INT16	y0;
+	IMG_INT16	x1;
+	IMG_INT16	y1;
+}IMG_RECT_16;
+
+
+typedef PVRSRV_ERROR (*PFN_GET_BUFFER_ADDR)(IMG_HANDLE,
+											IMG_HANDLE,
+											IMG_SYS_PHYADDR**,
+											IMG_SIZE_T*,
+											IMG_VOID**,
+											IMG_HANDLE*,
+											IMG_BOOL*,
+											IMG_BOOL*);
+
+typedef PVRSRV_ERROR (*PFN_GET_BUFFER_ID_FROM_TAG)(IMG_HANDLE, IMG_UINT32, IMG_HANDLE);
+
+typedef struct DISPLAY_DIMS_TAG
+{
+	IMG_UINT32	ui32ByteStride;
+	IMG_UINT32	ui32Width;
+	IMG_UINT32	ui32Height;
+} DISPLAY_DIMS;
+
+
+typedef struct DISPLAY_FORMAT_TAG
+{
+
+	PVRSRV_PIXEL_FORMAT		pixelformat;
+} DISPLAY_FORMAT;
+
+typedef struct DISPLAY_SURF_ATTRIBUTES_TAG
+{
+
+	PVRSRV_PIXEL_FORMAT		pixelformat;
+
+	DISPLAY_DIMS			sDims;
+	IMG_UINT32			ui32Reseved;
+} DISPLAY_SURF_ATTRIBUTES;
+
+
+typedef struct DISPLAY_MODE_INFO_TAG
+{
+
+	PVRSRV_PIXEL_FORMAT		pixelformat;
+
+	DISPLAY_DIMS			sDims;
+
+	IMG_UINT32				ui32RefreshHZ;
+
+	IMG_UINT32				ui32OEMFlags;
+} DISPLAY_MODE_INFO;
+
+
+
+#define MAX_DISPLAY_NAME_SIZE	(50)
+
+typedef struct DISPLAY_INFO_TAG
+{
+
+	IMG_UINT32 ui32MaxSwapChains;
+
+	IMG_UINT32 ui32MaxSwapChainBuffers;
+
+	IMG_UINT32 ui32MinSwapInterval;
+
+	IMG_UINT32 ui32MaxSwapInterval;
+
+	IMG_UINT32 ui32PhysicalWidthmm;
+	IMG_UINT32 ui32PhysicalHeightmm;
+
+	IMG_CHAR	szDisplayName[MAX_DISPLAY_NAME_SIZE];
+#if defined(SUPPORT_HW_CURSOR)
+
+	IMG_UINT16	ui32CursorWidth;
+	IMG_UINT16	ui32CursorHeight;
+#endif
+} DISPLAY_INFO;
+
+typedef struct ACCESS_INFO_TAG
+{
+	IMG_UINT32		ui32Size;
+	IMG_UINT32  	ui32FBPhysBaseAddress;
+	IMG_UINT32		ui32FBMemAvailable;
+	IMG_UINT32  	ui32SysPhysBaseAddress;
+	IMG_UINT32		ui32SysSize;
+	IMG_UINT32		ui32DevIRQ;
+}ACCESS_INFO;
+
+
+typedef struct PVRSRV_CURSOR_SHAPE_TAG
+{
+	IMG_UINT16			ui16Width;
+	IMG_UINT16			ui16Height;
+	IMG_INT16			i16XHot;
+	IMG_INT16			i16YHot;
+
+
+	IMG_VOID*   		pvMask;
+	IMG_INT16  			i16MaskByteStride;
+
+
+	IMG_VOID*			pvColour;
+	IMG_INT16			i16ColourByteStride;
+	PVRSRV_PIXEL_FORMAT	eColourPixelFormat;
+} PVRSRV_CURSOR_SHAPE;
+
+#define PVRSRV_SET_CURSOR_VISIBILITY	(1<<0)
+#define PVRSRV_SET_CURSOR_POSITION		(1<<1)
+#define PVRSRV_SET_CURSOR_SHAPE			(1<<2)
+#define PVRSRV_SET_CURSOR_ROTATION		(1<<3)
+
+typedef struct PVRSRV_CURSOR_INFO_TAG
+{
+
+	IMG_UINT32 ui32Flags;
+
+
+	IMG_BOOL bVisible;
+
+
+	IMG_INT16 i16XPos;
+	IMG_INT16 i16YPos;
+
+
+	PVRSRV_CURSOR_SHAPE sCursorShape;
+
+
+	IMG_UINT32 ui32Rotation;
+
+} PVRSRV_CURSOR_INFO;
+
+
+typedef struct _PVRSRV_REGISTRY_INFO_
+{
+    IMG_UINT32		ui32DevCookie;
+    IMG_PCHAR		pszKey;
+    IMG_PCHAR		pszValue;
+    IMG_PCHAR		pszBuf;
+    IMG_UINT32		ui32BufSize;
+} PVRSRV_REGISTRY_INFO, *PPVRSRV_REGISTRY_INFO;
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReadRegistryString (PPVRSRV_REGISTRY_INFO psRegInfo);
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWriteRegistryString (PPVRSRV_REGISTRY_INFO psRegInfo);
+
+
+#define PVRSRV_BC_FLAGS_YUVCSC_CONFORMANT_RANGE	(0 << 0)
+#define PVRSRV_BC_FLAGS_YUVCSC_FULL_RANGE		(1 << 0)
+
+#define PVRSRV_BC_FLAGS_YUVCSC_BT601			(0 << 1)
+#define PVRSRV_BC_FLAGS_YUVCSC_BT709			(1 << 1)
+
+#define MAX_BUFFER_DEVICE_NAME_SIZE	(50)
+
+typedef struct BUFFER_INFO_TAG
+{
+	IMG_UINT32 			ui32BufferCount;
+	IMG_UINT32			ui32BufferDeviceID;
+	PVRSRV_PIXEL_FORMAT	pixelformat;
+	IMG_UINT32			ui32ByteStride;
+	IMG_UINT32			ui32Width;
+	IMG_UINT32			ui32Height;
+	IMG_UINT32			ui32Flags;
+	IMG_CHAR			szDeviceName[MAX_BUFFER_DEVICE_NAME_SIZE];
+} BUFFER_INFO;
+
+typedef enum _OVERLAY_DEINTERLACE_MODE_
+{
+	WEAVE=0x0,
+	BOB_ODD,
+	BOB_EVEN,
+	BOB_EVEN_NONINTERLEAVED
+} OVERLAY_DEINTERLACE_MODE;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/include4/sgx_options.h b/drivers/gpu/drm/emgd/pvr/include4/sgx_options.h
new file mode 100644
index 0000000..75d1286
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/sgx_options.h
@@ -0,0 +1,220 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if defined(DEBUG) || defined (INTERNAL_TEST)
+#define DEBUG_SET_OFFSET	OPTIONS_BIT0
+#define OPTIONS_BIT0		0x1
+#else
+#define OPTIONS_BIT0		0x0
+#endif
+
+#if defined(PDUMP) || defined (INTERNAL_TEST)
+#define PDUMP_SET_OFFSET	OPTIONS_BIT1
+#define OPTIONS_BIT1		(0x1 << 1)
+#else
+#define OPTIONS_BIT1		0x0
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) || defined (INTERNAL_TEST)
+#define PVRSRV_USSE_EDM_STATUS_DEBUG_SET_OFFSET		OPTIONS_BIT2
+#define OPTIONS_BIT2		(0x1 << 2)
+#else
+#define OPTIONS_BIT2		0x0
+#endif
+
+#if defined(SUPPORT_HW_RECOVERY) || defined (INTERNAL_TEST)
+#define SUPPORT_HW_RECOVERY_SET_OFFSET	OPTIONS_BIT3
+#define OPTIONS_BIT3		(0x1 << 3)
+#else
+#define OPTIONS_BIT3		0x0
+#endif
+
+
+
+#if defined(PVR_SECURE_HANDLES) || defined (INTERNAL_TEST)
+#define PVR_SECURE_HANDLES_SET_OFFSET	OPTIONS_BIT4
+#define OPTIONS_BIT4		(0x1 << 4)
+#else
+#define OPTIONS_BIT4		0x0
+#endif
+
+#if defined(SGX_BYPASS_SYSTEM_CACHE) || defined (INTERNAL_TEST)
+#define SGX_BYPASS_SYSTEM_CACHE_SET_OFFSET	OPTIONS_BIT5
+#define OPTIONS_BIT5		(0x1 << 5)
+#else
+#define OPTIONS_BIT5		0x0
+#endif
+
+#if defined(SGX_DMS_AGE_ENABLE) || defined (INTERNAL_TEST)
+#define SGX_DMS_AGE_ENABLE_SET_OFFSET	OPTIONS_BIT6
+#define OPTIONS_BIT6		(0x1 << 6)
+#else
+#define OPTIONS_BIT6		0x0
+#endif
+
+#if defined(SGX_FAST_DPM_INIT) || defined (INTERNAL_TEST)
+#define SGX_FAST_DPM_INIT_SET_OFFSET	OPTIONS_BIT8
+#define OPTIONS_BIT8		(0x1 << 8)
+#else
+#define OPTIONS_BIT8		0x0
+#endif
+
+#if defined(SGX_FEATURE_DCU) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_DCU_SET_OFFSET	OPTIONS_BIT9
+#define OPTIONS_BIT9		(0x1 << 9)
+#else
+#define OPTIONS_BIT9		0x0
+#endif
+
+#if defined(SGX_FEATURE_MP) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_MP_SET_OFFSET	OPTIONS_BIT10
+#define OPTIONS_BIT10		(0x1 << 10)
+#else
+#define OPTIONS_BIT10		0x0
+#endif
+
+#if defined(SGX_FEATURE_MULTITHREADED_UKERNEL) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_MULTITHREADED_UKERNEL_SET_OFFSET	OPTIONS_BIT11
+#define OPTIONS_BIT11		(0x1 << 11)
+#else
+#define OPTIONS_BIT11		0x0
+#endif
+
+
+
+#if defined(SGX_FEATURE_OVERLAPPED_SPM) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_OVERLAPPED_SPM_SET_OFFSET	OPTIONS_BIT12
+#define OPTIONS_BIT12		(0x1 << 12)
+#else
+#define OPTIONS_BIT12		0x0
+#endif
+
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_SYSTEM_CACHE_SET_OFFSET	OPTIONS_BIT13
+#define OPTIONS_BIT13		(0x1 << 13)
+#else
+#define OPTIONS_BIT13		0x0
+#endif
+
+#if defined(SGX_SUPPORT_HWPROFILING) || defined (INTERNAL_TEST)
+#define SGX_SUPPORT_HWPROFILING_SET_OFFSET	OPTIONS_BIT14
+#define OPTIONS_BIT14		(0x1 << 14)
+#else
+#define OPTIONS_BIT14		0x0
+#endif
+
+
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) || defined (INTERNAL_TEST)
+#define SUPPORT_ACTIVE_POWER_MANAGEMENT_SET_OFFSET	OPTIONS_BIT15
+#define OPTIONS_BIT15		(0x1 << 15)
+#else
+#define OPTIONS_BIT15		0x0
+#endif
+
+#if defined(SUPPORT_DISPLAYCONTROLLER_TILING) || defined (INTERNAL_TEST)
+#define SUPPORT_DISPLAYCONTROLLER_TILING_SET_OFFSET	OPTIONS_BIT16
+#define OPTIONS_BIT16		(0x1 << 16)
+#else
+#define OPTIONS_BIT16		0x0
+#endif
+
+#if defined(SUPPORT_PERCONTEXT_PB) || defined (INTERNAL_TEST)
+#define SUPPORT_PERCONTEXT_PB_SET_OFFSET	OPTIONS_BIT17
+#define OPTIONS_BIT17		(0x1 << 17)
+#else
+#define OPTIONS_BIT17		0x0
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_HWPERF_SET_OFFSET	OPTIONS_BIT18
+#define OPTIONS_BIT18		(0x1 << 18)
+#else
+#define OPTIONS_BIT18		0x0
+#endif
+
+
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_MMU_DUMMY_PAGE_SET_OFFSET	OPTIONS_BIT19
+#define OPTIONS_BIT19		(0x1 << 19)
+#else
+#define OPTIONS_BIT19		0x0
+#endif
+
+#if defined(SUPPORT_SGX_PRIORITY_SCHEDULING) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_PRIORITY_SCHEDULING_SET_OFFSET	OPTIONS_BIT20
+#define OPTIONS_BIT20		(0x1 << 20)
+#else
+#define OPTIONS_BIT20		0x0
+#endif
+
+#if defined(SGX_LOW_LATENCY_SCHEDULING) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_LOW_LATENCY_SCHEDULING_SET_OFFSET	OPTIONS_BIT21
+#define OPTIONS_BIT21		(0x1 << 21)
+#else
+#define OPTIONS_BIT21		0x0
+#endif
+
+#if defined(USE_SUPPORT_NO_TA3D_OVERLAP) || defined (INTERNAL_TEST)
+#define USE_SUPPORT_NO_TA3D_OVERLAP_SET_OFFSET	OPTIONS_BIT22
+#define OPTIONS_BIT22		(0x1 << 22)
+#else
+#define OPTIONS_BIT22		0x0
+#endif
+
+
+#if defined(SGX_FEATURE_MP) || defined (INTERNAL_TEST)
+#define OPTIONS_HIGHBYTE ((SGX_FEATURE_MP_CORE_COUNT-1) << SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET)
+#define SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET	28UL
+#define SGX_FEATURE_MP_CORE_COUNT_SET_MASK		0xFF
+#else
+#define OPTIONS_HIGHBYTE	0x0
+#endif
+
+
+
+#define SGX_BUILD_OPTIONS	\
+	OPTIONS_BIT0 |\
+	OPTIONS_BIT1 |\
+	OPTIONS_BIT2 |\
+	OPTIONS_BIT3 |\
+	OPTIONS_BIT4 |\
+	OPTIONS_BIT5 |\
+	OPTIONS_BIT6 |\
+	OPTIONS_BIT8 |\
+	OPTIONS_BIT9 |\
+	OPTIONS_BIT10 |\
+	OPTIONS_BIT11 |\
+	OPTIONS_BIT12 |\
+	OPTIONS_BIT13 |\
+	OPTIONS_BIT14 |\
+	OPTIONS_BIT15 |\
+	OPTIONS_BIT16 |\
+	OPTIONS_BIT17 |\
+	OPTIONS_BIT18 |\
+	OPTIONS_BIT19 |\
+	OPTIONS_BIT20 |\
+	OPTIONS_BIT21 |\
+	OPTIONS_HIGHBYTE
+
diff --git a/drivers/gpu/drm/emgd/pvr/include4/sgxapi_km.h b/drivers/gpu/drm/emgd/pvr/include4/sgxapi_km.h
new file mode 100644
index 0000000..5302204
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/sgxapi_km.h
@@ -0,0 +1,323 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __SGXAPI_KM_H__
+#define __SGXAPI_KM_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "sgxdefs.h"
+
+#if defined(__linux__) && !defined(USE_CODE)
+	#if defined(__KERNEL__)
+		#include <asm/unistd.h>
+	#else
+		#include <unistd.h>
+	#endif
+#endif
+
+#define SGX_UNDEFINED_HEAP_ID					(~0LU)
+#define SGX_GENERAL_HEAP_ID						0
+#define SGX_TADATA_HEAP_ID						1
+#define SGX_KERNEL_CODE_HEAP_ID					2
+#define SGX_KERNEL_DATA_HEAP_ID					3
+#define SGX_PIXELSHADER_HEAP_ID					4
+#define SGX_VERTEXSHADER_HEAP_ID				5
+#define SGX_PDSPIXEL_CODEDATA_HEAP_ID			6
+#define SGX_PDSVERTEX_CODEDATA_HEAP_ID			7
+#define SGX_SYNCINFO_HEAP_ID					8
+#define SGX_3DPARAMETERS_HEAP_ID				9
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+#define SGX_GENERAL_MAPPING_HEAP_ID				10
+#endif
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define SGX_2D_HEAP_ID							11
+#else
+#if defined(FIX_HW_BRN_26915)
+#define SGX_CGBUFFER_HEAP_ID					12
+#endif
+#endif
+#if defined(SUPPORT_SGX_VIDEO_HEAP)
+#define SGX_VIDEO_HEAP_ID						13
+#define SGX_MAX_HEAP_ID							14
+#else
+#define SGX_MAX_HEAP_ID							13
+#endif
+
+#define SGX_MAX_TA_STATUS_VALS	32
+#define SGX_MAX_3D_STATUS_VALS	3
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+#define SGX_MAX_TA_DST_SYNCS			1
+#define SGX_MAX_TA_SRC_SYNCS			1
+#define SGX_MAX_3D_SRC_SYNCS			4
+#else
+#define SGX_MAX_SRC_SYNCS				4
+#endif
+
+#ifdef SUPPORT_SGX_HWPERF
+
+#define	PVRSRV_SGX_HWPERF_NUM_COUNTERS	9
+
+#define PVRSRV_SGX_HWPERF_INVALID					0x1
+
+#define PVRSRV_SGX_HWPERF_TRANSFER					0x2
+#define PVRSRV_SGX_HWPERF_TA						0x3
+#define PVRSRV_SGX_HWPERF_3D						0x4
+#define PVRSRV_SGX_HWPERF_2D						0x5
+
+#define PVRSRV_SGX_HWPERF_MK_EVENT					0x101
+#define PVRSRV_SGX_HWPERF_MK_TA						0x102
+#define PVRSRV_SGX_HWPERF_MK_3D						0x103
+#define PVRSRV_SGX_HWPERF_MK_2D						0x104
+
+#define PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT			28
+#define PVRSRV_SGX_HWPERF_TYPE_OP_MASK				((1UL << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT) - 1)
+#define PVRSRV_SGX_HWPERF_TYPE_OP_START				(0UL << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT)
+#define PVRSRV_SGX_HWPERF_TYPE_OP_END				(1Ul << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT)
+
+#define PVRSRV_SGX_HWPERF_TYPE_TRANSFER_START		(PVRSRV_SGX_HWPERF_TRANSFER | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_TRANSFER_END			(PVRSRV_SGX_HWPERF_TRANSFER | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_TA_START				(PVRSRV_SGX_HWPERF_TA | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_TA_END				(PVRSRV_SGX_HWPERF_TA | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_3D_START				(PVRSRV_SGX_HWPERF_3D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_3D_END				(PVRSRV_SGX_HWPERF_3D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_2D_START				(PVRSRV_SGX_HWPERF_2D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_2D_END				(PVRSRV_SGX_HWPERF_2D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+
+#define PVRSRV_SGX_HWPERF_TYPE_MK_EVENT_START		(PVRSRV_SGX_HWPERF_MK_EVENT | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_EVENT_END			(PVRSRV_SGX_HWPERF_MK_EVENT | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_START			(PVRSRV_SGX_HWPERF_MK_TA | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_END			(PVRSRV_SGX_HWPERF_MK_TA | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_START			(PVRSRV_SGX_HWPERF_MK_3D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_END			(PVRSRV_SGX_HWPERF_MK_3D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_START			(PVRSRV_SGX_HWPERF_MK_2D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_END			(PVRSRV_SGX_HWPERF_MK_2D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+
+#define PVRSRV_SGX_HWPERF_OFF						(0x0)
+#define PVRSRV_SGX_HWPERF_GRAPHICS_ON				(1UL << 0)
+#define PVRSRV_SGX_HWPERF_MK_EXECUTION_ON			(1UL << 1)
+
+
+typedef struct _PVRSRV_SGX_HWPERF_CB_ENTRY_
+{
+	IMG_UINT32	ui32FrameNo;
+	IMG_UINT32	ui32Type;
+	IMG_UINT32	ui32Ordinal;
+	IMG_UINT32	ui32Clocksx16;
+	IMG_UINT32	ui32Counters[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+} PVRSRV_SGX_HWPERF_CB_ENTRY;
+
+
+typedef struct _PVRSRV_SGX_HWPERF_CBDATA_
+{
+	IMG_UINT32	ui32FrameNo;
+	IMG_UINT32	ui32Type;
+	IMG_UINT32	ui32StartTimeWraps;
+	IMG_UINT32	ui32StartTime;
+	IMG_UINT32	ui32EndTimeWraps;
+	IMG_UINT32	ui32EndTime;
+	IMG_UINT32	ui32ClockSpeed;
+	IMG_UINT32	ui32TimeMax;
+} PVRSRV_SGX_HWPERF_CBDATA;
+
+
+typedef struct _SGX_MISC_INFO_HWPERF_RETRIEVE_CB
+{
+	PVRSRV_SGX_HWPERF_CBDATA*	psHWPerfData;
+	IMG_UINT32					ui32ArraySize;
+	IMG_UINT32					ui32DataCount;
+	IMG_UINT32					ui32Time;
+} SGX_MISC_INFO_HWPERF_RETRIEVE_CB;
+#endif
+
+
+typedef struct _CTL_STATUS_
+{
+	IMG_DEV_VIRTADDR	sStatusDevAddr;
+	IMG_UINT32			ui32StatusValue;
+} CTL_STATUS;
+
+
+typedef enum _SGX_MISC_INFO_REQUEST_
+{
+	SGX_MISC_INFO_REQUEST_CLOCKSPEED = 0,
+	SGX_MISC_INFO_REQUEST_SGXREV,
+	SGX_MISC_INFO_REQUEST_DRIVER_SGXREV,
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+	SGX_MISC_INFO_REQUEST_MEMREAD,
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+	SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS,
+	SGX_MISC_INFO_REQUEST_HWPERF_CB_ON,
+	SGX_MISC_INFO_REQUEST_HWPERF_CB_OFF,
+	SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB,
+#endif
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+	SGX_MISC_INFO_REQUEST_SET_BREAKPOINT,
+#endif
+	SGX_MISC_INFO_DUMP_DEBUG_INFO,
+	SGX_MISC_INFO_PANIC,
+	SGX_MISC_INFO_REQUEST_FORCE_I16 				=  0x7fff
+} SGX_MISC_INFO_REQUEST;
+
+
+typedef struct _PVRSRV_SGX_MISCINFO_FEATURES
+{
+	IMG_UINT32			ui32CoreRev;
+	IMG_UINT32			ui32CoreID;
+	IMG_UINT32			ui32DDKVersion;
+	IMG_UINT32			ui32DDKBuild;
+	IMG_UINT32			ui32CoreIdSW;
+	IMG_UINT32			ui32CoreRevSW;
+	IMG_UINT32			ui32BuildOptions;
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+	IMG_UINT32			ui32DeviceMemValue;
+#endif
+} PVRSRV_SGX_MISCINFO_FEATURES;
+
+
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+typedef struct _SGX_BREAKPOINT_INFO
+{
+
+	IMG_BOOL					bBPEnable;
+
+
+
+	IMG_UINT32					ui32BPIndex;
+
+	IMG_DEV_VIRTADDR			sBPDevVAddr;
+} SGX_BREAKPOINT_INFO;
+#endif
+
+typedef struct _SGX_MISC_INFO_
+{
+	SGX_MISC_INFO_REQUEST	eRequest;
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+	IMG_DEV_VIRTADDR			sDevVAddr;
+	IMG_HANDLE					hDevMemContext;
+#endif
+	union
+	{
+		IMG_UINT32	reserved;
+		PVRSRV_SGX_MISCINFO_FEATURES						sSGXFeatures;
+		IMG_UINT32											ui32SGXClockSpeed;
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+		SGX_BREAKPOINT_INFO									sSGXBreakpointInfo;
+#endif
+#ifdef SUPPORT_SGX_HWPERF
+		IMG_UINT32											ui32NewHWPerfStatus;
+		SGX_MISC_INFO_HWPERF_RETRIEVE_CB					sRetrieveCB;
+#endif
+	} uData;
+} SGX_MISC_INFO;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define PVRSRV_MAX_BLT_SRC_SYNCS		3
+#endif
+
+
+#define SGX_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH		256
+
+typedef struct _SGX_KICKTA_DUMPBITMAP_
+{
+	IMG_DEV_VIRTADDR	sDevBaseAddr;
+	IMG_UINT32			ui32Flags;
+	IMG_UINT32			ui32Width;
+	IMG_UINT32			ui32Height;
+	IMG_UINT32			ui32Stride;
+	IMG_UINT32			ui32PDUMPFormat;
+	IMG_UINT32			ui32BytesPP;
+	IMG_CHAR			pszName[SGX_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH];
+} SGX_KICKTA_DUMPBITMAP, *PSGX_KICKTA_DUMPBITMAP;
+
+#define PVRSRV_SGX_PDUMP_CONTEXT_MAX_BITMAP_ARRAY_SIZE	(16)
+
+typedef struct _PVRSRV_SGX_PDUMP_CONTEXT_
+{
+
+	IMG_UINT32						ui32CacheControl;
+
+} PVRSRV_SGX_PDUMP_CONTEXT;
+
+
+typedef struct _SGX_KICKTA_DUMP_ROFF_
+{
+	IMG_HANDLE			hKernelMemInfo;
+	IMG_UINT32			uiAllocIndex;
+	IMG_UINT32			ui32Offset;
+	IMG_UINT32			ui32Value;
+	IMG_PCHAR			pszName;
+} SGX_KICKTA_DUMP_ROFF, *PSGX_KICKTA_DUMP_ROFF;
+
+typedef struct _SGX_KICKTA_DUMP_BUFFER_
+{
+	IMG_UINT32			ui32SpaceUsed;
+	IMG_UINT32			ui32Start;
+	IMG_UINT32			ui32End;
+	IMG_UINT32			ui32BufferSize;
+	IMG_UINT32			ui32BackEndLength;
+	IMG_UINT32			uiAllocIndex;
+	IMG_HANDLE			hKernelMemInfo;
+	IMG_PVOID			pvLinAddr;
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+	IMG_HANDLE			hCtrlKernelMemInfo;
+	IMG_DEV_VIRTADDR	sCtrlDevVAddr;
+#endif
+	IMG_PCHAR			pszName;
+} SGX_KICKTA_DUMP_BUFFER, *PSGX_KICKTA_DUMP_BUFFER;
+
+#ifdef PDUMP
+typedef struct _SGX_KICKTA_PDUMP_
+{
+
+	PSGX_KICKTA_DUMPBITMAP		psPDumpBitmapArray;
+	IMG_UINT32						ui32PDumpBitmapSize;
+
+
+	PSGX_KICKTA_DUMP_BUFFER	psBufferArray;
+	IMG_UINT32						ui32BufferArraySize;
+
+
+	PSGX_KICKTA_DUMP_ROFF		psROffArray;
+	IMG_UINT32						ui32ROffArraySize;
+} SGX_KICKTA_PDUMP, *PSGX_KICKTA_PDUMP;
+#endif
+
+#if defined(TRANSFER_QUEUE)
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define SGX_MAX_2D_BLIT_CMD_SIZE 		26
+#define SGX_MAX_2D_SRC_SYNC_OPS			3
+#endif
+#define SGX_MAX_TRANSFER_STATUS_VALS	2
+#define SGX_MAX_TRANSFER_SYNC_OPS	5
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/include4/sgxscript.h b/drivers/gpu/drm/emgd/pvr/include4/sgxscript.h
new file mode 100644
index 0000000..c6d080b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/include4/sgxscript.h
@@ -0,0 +1,77 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __SGXSCRIPT_H__
+#define __SGXSCRIPT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define	SGX_MAX_INIT_COMMANDS	64
+#define	SGX_MAX_DEINIT_COMMANDS	16
+
+typedef	enum _SGX_INIT_OPERATION
+{
+	SGX_INIT_OP_ILLEGAL = 0,
+	SGX_INIT_OP_WRITE_HW_REG,
+#if defined(PDUMP)
+	SGX_INIT_OP_PDUMP_HW_REG,
+#endif
+	SGX_INIT_OP_HALT
+} SGX_INIT_OPERATION;
+
+typedef union _SGX_INIT_COMMAND
+{
+	SGX_INIT_OPERATION eOp;
+	struct {
+		SGX_INIT_OPERATION eOp;
+		IMG_UINT32 ui32Offset;
+		IMG_UINT32 ui32Value;
+	} sWriteHWReg;
+#if defined(PDUMP)
+	struct {
+		SGX_INIT_OPERATION eOp;
+		IMG_UINT32 ui32Offset;
+		IMG_UINT32 ui32Value;
+	} sPDumpHWReg;
+#endif
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+	struct {
+		SGX_INIT_OPERATION eOp;
+	} sWorkaroundBRN22997;
+#endif
+} SGX_INIT_COMMAND;
+
+typedef struct _SGX_INIT_SCRIPTS_
+{
+	SGX_INIT_COMMAND asInitCommandsPart1[SGX_MAX_INIT_COMMANDS];
+	SGX_INIT_COMMAND asInitCommandsPart2[SGX_MAX_INIT_COMMANDS];
+	SGX_INIT_COMMAND asDeinitCommands[SGX_MAX_DEINIT_COMMANDS];
+} SGX_INIT_SCRIPTS;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.c b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.c
new file mode 100644
index 0000000..b6fc6d6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.c
@@ -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/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.h b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.h
new file mode 100644
index 0000000..7728631
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc.h
@@ -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/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc_linux.c b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc_linux.c
new file mode 100644
index 0000000..983b768
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_bufferclass/emgd_bc_linux.c
@@ -0,0 +1,1000 @@
+/****************************************************************************
+ *
+ * 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/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c
new file mode 100644
index 0000000..b7a879a2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.c
@@ -0,0 +1,2814 @@
+/**********************************************************************
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION 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;
+
+		if(!buffers[i].is_contiguous){		
+			for (i = 0 ; i < swap_chain->buffer_count ; i++) {
+				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[0].virt_addr);
+		}
+	}
+
+	if (swap_chain->flip_queue) {
+		OS_FREE(swap_chain->flip_queue);
+	}
+	OS_FREE(swap_chain->buffers);
+	OS_FREE(swap_chain);
+
+	EMGD_TRACE_EXIT;
+} /* free_swap_chain() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnCreateDCSwapChain()
+ * function.  This function was originally designed to create a flip-able swap
+ * chain on the specified device, but has also been augmented to allow the X
+ * driver to create pixmaps or other buffers in GTT memory.  A flip-able swap
+ * chain consists of a front buffer (the "system buffer, a.k.a. the "frame
+ * buffer") and one or more back buffers (therefore, the number of buffers
+ * includes the frame buffer).
+ *
+ * Note: Only full-screen flipping is supported (the hardware is pointed at one
+ * complete buffer at a time).  There is no support for the
+ * SetDC{Src|Dst}Rect() functions to define a smaller region of the display for
+ * the buffers/flipping.
+ *
+ * Note: The DDK documentation says that the mode should be changed if the
+ * dimensions and pixel format do not match the current dimensions and pixel
+ * format.  However, this can only be supported if the X server isn't running
+ * (which is in charge of changing modes when it is running).  If the X server
+ * is running, an error is returned unless the current dimensions and pixel
+ * format are specified.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param flags (IN) Unused.
+ * @param dst_surf_attrib (IN) While not described in the DDK documentation,
+ * this presumably specifies the desired dimensions and pixel format of the
+ * front buffer.
+ * @param src_surf_attrib (IN) Specifies the desired dimensions and pixel
+ * format of the back buffers.
+ * @param buffer_count (IN) Number of buffers required in this swap chain.
+ * @param sync_data (IN) While not described in the DDK documentation,
+ * this is an array of sync data for each buffer.
+ * @param oem_flags (IN) Unused.
+ * @param swap_chain_h (OUT) The handle for this swap chain (an opaque pointer
+ * to a emgddc_swapchain_t).
+ * @param swap_chain_id (OUT) Unused.
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE device_h,
+	IMG_UINT32 flags,
+	DISPLAY_SURF_ATTRIBUTES *dst_surf_attrib,
+	DISPLAY_SURF_ATTRIBUTES *src_surf_attrib,
+	IMG_UINT32 buffer_count,
+	PVRSRV_SYNC_DATA **sync_data,
+	IMG_UINT32 oem_flags,
+	IMG_HANDLE *swap_chain_h,
+	IMG_UINT32 *swap_chain_id)
+{
+	emgddc_devinfo_t	*devinfo;
+	emgddc_swapchain_t *swap_chain;
+	emgddc_buffer_t *buffers;
+	IMG_UINT32 i;
+	emgddc_flip_queue_item_t *flip_queue = NULL;
+	unsigned long lock_flags;
+
+	struct drm_device* drm_dev;
+	drm_emgd_priv_t *priv;
+	igd_context_t *context;
+	igd_dispatch_t *dispatch;
+	int flipable;
+
+	IMG_UINT32 ci_offset=0;
+
+
+	EMGD_TRACE_ENTER;
+	EMGD_DEBUG("device_h = 0x%p, buffer_count = %lu", device_h, buffer_count);
+	EMGD_DEBUG("flags = 0x%08lx, oem_flags = 0x%08lx", flags, oem_flags);
+	
+	if(flags & PVR2D_CREATE_FLIPCHAIN_CI)
+	{	
+		ci_offset = src_surf_attrib->ui32Reseved;		
+		
+	}
+		
+	/*
+	 * Check the parameters and dependencies:
+	 */
+	if (!device_h || !dst_surf_attrib || !src_surf_attrib || !sync_data ||
+		!swap_chain_h) {
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/*
+	 * The oem_flags will determine what type of swapchain this is.  The
+	 * following types are for a non-flip-able swap chain (e.g. for a pixmap):
+	 *
+	 *  PVR2D_CREATE_FLIPCHAIN_OEMDISPLAY - General purpose displayable
+	 *  PVR2D_CREATE_FLIPCHAIN_OEMGENERAL - General purpose non-displayable
+	 *  PVR2D_CREATE_FLIPCHAIN_OEMOVERLAY - Overlay
+	 *
+	 *  Currently, if none of these flags are set, assume this is going
+	 *  to create a set of back buffers, or a "flip-able" swap chain:
+	 *
+	 *  PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN - Flip-able buffers
+	 */
+	/* Is this is an OEM call (I.E. allocating a buffer)? */
+	if ((oem_flags & (PVR2D_CREATE_FLIPCHAIN_OEMDISPLAY |
+				PVR2D_CREATE_FLIPCHAIN_OEMGENERAL |
+				PVR2D_CREATE_FLIPCHAIN_OEMOVERLAY |
+				PVR2D_CREATE_FLIPCHAIN_CI))) {
+		flipable = 0;
+		
+	} else {
+		/*
+		 * If this is suppose to be an actual flip-able swap chain, then
+		 * make sure there are at least 2 buffers.
+		 */
+		if (buffer_count < 2) {
+			return PVRSRV_ERROR_TOO_FEW_BUFFERS;
+		}
+		flipable = 1;
+		
+	}
+
+	devinfo = (emgddc_devinfo_t *) device_h;
+	if (!is_valid_devinfo(devinfo)) {
+		printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
+			__FUNCTION__, devinfo);
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	drm_dev = devinfo->drm_device;
+	priv = drm_dev->dev_private;
+	context = priv->context;
+	dispatch = &(context->dispatch);
+
+
+	if (buffer_count > devinfo->display_info.ui32MaxSwapChainBuffers) {
+		return PVRSRV_ERROR_TOOMANYBUFFERS;
+	}
+
+	/* Ensure the source & destination attributes match each other: */
+	if ((dst_surf_attrib->pixelformat != src_surf_attrib->pixelformat) ||
+		(dst_surf_attrib->sDims.ui32ByteStride !=
+		src_surf_attrib->sDims.ui32ByteStride) ||
+		(dst_surf_attrib->sDims.ui32Width != src_surf_attrib->sDims.ui32Width)||
+		(dst_surf_attrib->sDims.ui32Height !=
+		src_surf_attrib->sDims.ui32Height)) {
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if (flipable) {
+		PVRSRV_ERROR err =
+			do_mode_change(context, devinfo, priv, dst_surf_attrib);
+		if (err != PVRSRV_OK) {
+			EMGD_DEBUG("Exiting early because of an error in do_mode_change()");
+			EMGD_TRACE_EXIT;
+			return err;
+		}
+	}
+
+	/*
+	 * Allocate data structures:
+	 */
+	swap_chain = (emgddc_swapchain_t *) OS_ALLOC(sizeof(emgddc_swapchain_t));
+	if (!swap_chain) {
+		EMGD_ERROR_EXIT("Can not allocate memory for a swap chain");
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	OS_MEMSET(swap_chain, 0, sizeof(emgddc_swapchain_t));
+
+	buffers = (emgddc_buffer_t *) OS_ALLOC(sizeof(emgddc_buffer_t) *
+		buffer_count);
+	if (!buffers) {
+		OS_FREE(swap_chain);
+		EMGD_ERROR_EXIT("Can not allocate memory for swap chain buffers");
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	OS_MEMSET(buffers, 0, sizeof(emgddc_buffer_t) * buffer_count);
+
+	if (flipable) {
+		flip_queue = (emgddc_flip_queue_item_t *)
+			OS_ALLOC(sizeof(emgddc_flip_queue_item_t) * buffer_count);
+		if (!flip_queue) {
+			OS_FREE(buffers);
+			OS_FREE(swap_chain);
+			EMGD_ERROR_EXIT("Can not allocate memory for flip queue");
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		}
+		OS_MEMSET(flip_queue, 0,
+			sizeof(emgddc_flip_queue_item_t) * buffer_count);
+	}
+
+	/*
+	 * Initialize data structures:
+	 */
+	swap_chain->devinfo = devinfo;
+	swap_chain->valid = EMGD_TRUE;
+	swap_chain->buffer_count = (unsigned long) buffer_count;
+	swap_chain->buffers = buffers;
+	swap_chain->flags = flags;
+	swap_chain->next = NULL;
+	if (flipable) {
+		swap_chain->flip_queue = flip_queue;
+		swap_chain->insert_index = 0;
+		swap_chain->remove_index = 0;
+	}
+	swap_chain->pvr_jtable = &devinfo->pvr_jtable;
+
+	/* Link the buffers of the swap chain: */
+	for (i = 0 ; i < buffer_count-1 ; i++) {
+		buffers[i].next = &buffers[i+1];
+	}
+	buffers[i].next = &buffers[0];
+
+	i = 0;
+	if (flipable) {
+		/* The first buffer is the frame buffer (a.k.a. the front buffer). */
+		buffers[i].priv = priv;
+		buffers[i].offset = devinfo->system_buffer.offset;
+		buffers[i].pixel_format = devinfo->system_buffer.pixel_format;
+		buffers[i].width = devinfo->system_buffer.width;
+		buffers[i].height = devinfo->system_buffer.height;
+		buffers[i].pitch = devinfo->system_buffer.pitch;
+		buffers[i].size = devinfo->system_buffer.size;
+		buffers[i].virt_addr = devinfo->system_buffer.virt_addr;
+		buffers[i].sync_data = sync_data[0];
+		buffers[i].is_fb = 1;
+		swap_chain->flags |= PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN;
+		i++;
+	}
+
+	/*
+	 * Allocate memory for the buffers
+	 */
+	for (; i < buffer_count ; i++) {
+		unsigned long offset;
+		unsigned long virt_addr;
+		unsigned int width = 0;
+		unsigned int height = 0;
+		unsigned int pitch = 0;
+		unsigned long size = 0;
+		unsigned long pf;
+		unsigned long flags = IGD_SURFACE_RENDER;
+		int ret;
+		unsigned int map_method=1;	/*1: gtt map by va driver*/
+
+		if (!(oem_flags & PVR2D_CREATE_FLIPCHAIN_OEMGENERAL)) {
+			flags |= IGD_SURFACE_DISPLAY;
+		}
+
+		buffers[i].priv = priv;
+
+		/*
+		 * What should be used for the surface attributes, the source
+		 * surface attributes or the destination surface attributes?
+		 * Can we assume that source is the surface requested?
+		 */
+		pf = pvr2emgd_pf(dst_surf_attrib->pixelformat);
+		width = dst_surf_attrib->sDims.ui32Width;
+		height = dst_surf_attrib->sDims.ui32Height;
+		pitch = dst_surf_attrib->sDims.ui32ByteStride;
+		flags |= IGD_MIN_PITCH;
+		
+		if(oem_flags & PVR2D_CREATE_FLIPCHAIN_CI){
+			if(oem_flags & PVR2D_CREATE_FLIPCHAIN_CI_V4L2_MAP)
+				map_method = 0;		
+
+
+			size=height*pitch;
+			ret = dispatch->gmm_map_ci(&offset,
+				ci_offset,	
+				&virt_addr,		
+				map_method,
+				size);
+			
+						
+			if (0 != ret) {
+				free_swap_chain(swap_chain, context);
+				EMGD_ERROR_EXIT("gmm_alloc_surface() failed (%d)", ret);
+				return PVRSRV_ERROR_OUT_OF_MEMORY;
+			}
+			buffers[i].is_contiguous = IMG_TRUE;
+
+		}
+		else{
+			
+			ret = dispatch->gmm_alloc_surface(&offset,
+				pf,
+				&width, &height,
+				&pitch, &size,
+				IGD_GMM_ALLOC_TYPE_NORMAL, &flags);
+			if (0 != ret) {
+				free_swap_chain(swap_chain, context);
+				EMGD_ERROR_EXIT("gmm_alloc_surface() failed (%d)", ret);
+				return PVRSRV_ERROR_OUT_OF_MEMORY;
+			}
+			buffers[i].is_contiguous = IMG_FALSE;
+		}
+
+		dst_surf_attrib->sDims.ui32ByteStride = pitch;
+		src_surf_attrib->sDims.ui32ByteStride = pitch;
+
+		buffers[i].pixel_format = pf;
+		buffers[i].width = width;
+		buffers[i].height = height;
+		buffers[i].pitch = pitch;
+		buffers[i].size = (size + (PAGE_SIZE - 1)) & PAGE_MASK;
+		
+		buffers[i].offset = offset;		
+		
+		if(oem_flags & PVR2D_CREATE_FLIPCHAIN_CI){			
+			
+				buffers[i].virt_addr = (IMG_CPU_VIRTADDR)virt_addr;			
+		}
+		else
+			buffers[i].virt_addr = dispatch->gmm_map(offset);
+		buffers[i].sync_data = sync_data[i];
+		buffers[i].is_fb = 0;
+	} /* for */
+
+
+	if (flipable) {
+		/* Initialize what's needed for flip-able swap chains: */
+		int must_enable;
+
+		for (i = 0 ; i < buffer_count ; i++) {
+			flip_queue[i].valid = EMGD_FALSE;
+			flip_queue[i].flipped = EMGD_FALSE;
+			flip_queue[i].cmd_completed = EMGD_FALSE;
+		}
+
+		spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+
+		must_enable = (devinfo->flipable_swapchains == NULL) ? 1 : 0;
+
+		/* Add this swap chain to the list of flip-able swap chains: */
+		add_swap_chain_to_list(&devinfo->flipable_swapchains, swap_chain);
+
+		/* Unlock here (before enabling interrupts), to prevent deadlock: */
+		spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+
+		if (!devinfo->flush_commands) {
+			if (must_enable) {
+				/* Enable interrupts for vblanks: */
+				if (!devinfo->interrupt_h || dispatch->
+					enable_vblank_callback(devinfo->interrupt_h)) {
+					/* For some reason (rare), interrupts weren't enabled: */
+					EMGD_ERROR_EXIT("Can not enable VBlank interrupts!  "
+									"Therefore, cannot do buffer flipping!");
+					/* Properly clean up: */
+					remove_swap_chain_from_list(&devinfo->flipable_swapchains,
+												swap_chain);
+					free_swap_chain(swap_chain, context);
+					return PVRSRV_ERROR_BAD_MAPPING;
+				} else {
+					devinfo->flipping_disabled = EMGD_FALSE;
+				}
+			}
+		}
+
+#ifdef SUPPORT_FB_EVENTS
+		if (must_enable) {
+			/* Enable fb events: */
+			if (enable_event_notification(devinfo)!= EMGD_OK) {
+				EMGD_ERROR_EXIT("Can not enable framebuffer event "
+					"notification");
+				/* Properly clean up: */
+				if (devinfo->interrupt_h) {
+					dispatch->disable_vblank_callback(
+						devinfo->interrupt_h);
+				}
+				spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+				remove_swap_chain_from_list(&devinfo->flipable_swapchains,
+					swap_chain);
+				spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+				free_swap_chain(swap_chain, context);
+				return PVRSRV_ERROR_BAD_MAPPING;
+			}
+		}
+#endif /* SUPPORT_FB_EVENTS */
+	} else {
+		/* Add this swap chain to the list of pixmap swap chains: */
+		add_swap_chain_to_list(&devinfo->pixmap_swapchains, swap_chain);
+	}
+
+
+	*swap_chain_id = ++devinfo->swap_chain_id_counter;
+	*swap_chain_h = (IMG_HANDLE) swap_chain;
+	EMGD_DEBUG("swap_chain_h = 0x%p, *swap_chain_id = %lu",
+		swap_chain_h, *swap_chain_id);
+
+	EMGD_TRACE_EXIT;
+	return PVRSRV_OK;
+
+} /* CreateDCSwapChain() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnDestroyDCSwapChain()
+ * function.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
+ * to a emgddc_swapchain_t).
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE device_h,
+	IMG_HANDLE swap_chain_h)
+{
+	emgddc_devinfo_t	*devinfo;
+	drm_emgd_priv_t *priv;
+	igd_context_t *context;
+	igd_dispatch_t *dispatch;
+	emgddc_swapchain_t *swap_chain;
+	unsigned long lock_flags;
+#ifdef SUPPORT_FB_EVENTS
+	emgd_error_t error;
+#endif /* SUPPORT_FB_EVENTS */
+
+	EMGD_TRACE_ENTER;
+	EMGD_DEBUG("device_h = 0x%p", device_h);
+
+
+	if (!device_h || !swap_chain_h) {
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	devinfo = (emgddc_devinfo_t *) device_h;
+	priv = devinfo->priv;
+	context = priv->context;
+	dispatch = &(context->dispatch);
+	swap_chain = (emgddc_swapchain_t *) swap_chain_h;
+	if (!is_valid_swap_chain(devinfo, swap_chain, 0)) {
+		printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p) and/or "
+			"swap chain handle (0x%p)\n",__FUNCTION__, devinfo, swap_chain);
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* Remove swap chain from the appropriate list: */
+	if (swap_chain->flags & PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN) {
+		/* De-initialize what's needed for flip-able swap chains: */
+		int must_disable;
+		spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+		must_disable =
+			((devinfo->flipable_swapchains == swap_chain) &&
+			 (devinfo->flipable_swapchains->next == NULL)) ? 1 : 0;
+
+		/* Remove this swap chain from the list of flip-able swap chains: */
+		remove_swap_chain_from_list(&devinfo->flipable_swapchains, swap_chain);
+
+		spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+
+#ifdef SUPPORT_FB_EVENTS
+		if (must_disable) {
+			/* Disable fb events: */
+			error = disable_event_notification(devinfo);
+			if (error != EMGD_OK) {
+				EMGD_ERROR("Could not disable framebuffer event notification");
+			}
+		}
+#endif /* SUPPORT_FB_EVENTS */
+
+		/* Disable interrupts for vblanks: */
+		if (must_disable) {
+			if (devinfo->interrupt_h) {
+				dispatch->disable_vblank_callback(devinfo->interrupt_h);
+			}
+		}
+
+		/* Flush any pending flips: */
+		flush_flip_queue(swap_chain);
+
+		/* Flip back to the system buffer: */
+		emgddc_flip(swap_chain, &devinfo->system_buffer);
+	} else {
+		/* Remove this swap chain from the list of pixmap swap chains: */
+		remove_swap_chain_from_list(&devinfo->pixmap_swapchains, swap_chain);
+	}
+
+	/* Free all GMM and kernel space memory for this swap chain: */
+	free_swap_chain(swap_chain, context);
+
+	EMGD_TRACE_EXIT;
+	return PVRSRV_OK;
+
+} /* DestroyDCSwapChain() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCDstRect()
+ * function.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
+ * to a emgddc_swapchain_t).
+ * @param rect (IN) Unused.
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR SetDCDstRect(IMG_HANDLE device_h,
+	IMG_HANDLE swap_chain_h,
+	IMG_RECT *rect)
+{
+	UNREFERENCED_PARAMETER(device_h);
+	UNREFERENCED_PARAMETER(swap_chain_h);
+	UNREFERENCED_PARAMETER(rect);
+
+	EMGD_TRACE_STUB;
+
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCSrcRect()
+ * function.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
+ * to a emgddc_swapchain_t).
+ * @param rect (IN) Unused.
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR SetDCSrcRect(IMG_HANDLE device_h,
+	IMG_HANDLE swap_chain_h,
+	IMG_RECT *rect)
+{
+	UNREFERENCED_PARAMETER(device_h);
+	UNREFERENCED_PARAMETER(swap_chain_h);
+	UNREFERENCED_PARAMETER(rect);
+
+	EMGD_TRACE_STUB;
+
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCDstColourKey()
+ * function.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
+ * to a emgddc_swapchain_t).
+ * @param color (IN) Unused.
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR SetDCDstColourKey(IMG_HANDLE device_h,
+	IMG_HANDLE swap_chain_h,
+	IMG_UINT32 color)
+{
+	UNREFERENCED_PARAMETER(device_h);
+	UNREFERENCED_PARAMETER(swap_chain_h);
+	UNREFERENCED_PARAMETER(color);
+
+	EMGD_TRACE_STUB;
+
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCSrcColourKey()
+ * function.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
+ * to a emgddc_swapchain_t).
+ * @param color (IN) Unused.
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR SetDCSrcColourKey(IMG_HANDLE device_h,
+	IMG_HANDLE swap_chain_h,
+	IMG_UINT32 color)
+{
+	UNREFERENCED_PARAMETER(device_h);
+	UNREFERENCED_PARAMETER(swap_chain_h);
+	UNREFERENCED_PARAMETER(color);
+
+	EMGD_TRACE_STUB;
+
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnGetDCBuffers()
+ * function.
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
+ * to a emgddc_swapchain_t).
+ * @param buffer_count (OUT) The number of buffers in the specified swap chain.
+ * @param buffer_h (IN/OUT) An array of buffer handles (an opaque pointer to a
+ * emgddc_buffer_t) in the specified swap chain (memory must be allocated by
+ * the caller).
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR GetDCBuffers(IMG_HANDLE device_h,
+	IMG_HANDLE swap_chain_h,
+	IMG_UINT32 *buffer_count,
+	IMG_HANDLE *buffer_h)
+{
+	emgddc_devinfo_t *devinfo;
+	emgddc_swapchain_t *swap_chain;
+	unsigned long i;
+
+	EMGD_TRACE_ENTER;
+	EMGD_DEBUG("device_h = 0x%p", device_h);
+
+
+	if (!device_h || !swap_chain_h || !buffer_count || !buffer_h) {
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	devinfo = (emgddc_devinfo_t *) device_h;
+	swap_chain = (emgddc_swapchain_t *) swap_chain_h;
+	if (!is_valid_swap_chain(devinfo, swap_chain, 0)) {
+		printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p) and/or "
+			"swap chain handle (0x%p)\n",__FUNCTION__, devinfo, swap_chain);
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	*buffer_count = (IMG_UINT32) swap_chain->buffer_count;
+
+	for (i = 0 ; i < swap_chain->buffer_count ; i++) {
+		buffer_h[i] = (IMG_HANDLE) &swap_chain->buffers[i];
+	}
+
+
+	EMGD_TRACE_EXIT;
+	return PVRSRV_OK;
+
+} /* GetDCBuffers() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSwapToDCBuffer()
+ * function.  This function is supposed to cause a flip to the specified
+ * buffer.  However, it is no longer called by PVR services!
+ *
+ * NOTE: As can be seen, this function was never completely implemented
+ * (i.e. in the DDK used to create this version).  This is because the PVR code
+ * doesn't call this function.  Instead, it calls emgddc_process_flip().
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param buffer_h (IN) The handle for this buffer (an opaque pointer to a
+ * emgddc_buffer_t).
+ * @param swap_interval (IN) Unused.
+ * @param private_tag_h (IN) Unused.
+ * @param clip_rect_count (IN) Largely unused.
+ * @param clip_rect (IN) Unused.
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR SwapToDCBuffer(IMG_HANDLE device_h,
+	IMG_HANDLE buffer_h,
+	IMG_UINT32 swap_interval,
+	IMG_HANDLE private_tag_h,
+	IMG_UINT32 clip_rect_count,
+	IMG_RECT *clip_rect)
+{
+	/* This function is never called by PVR services, and so it is stubbed: */
+	UNREFERENCED_PARAMETER(device_h);
+	UNREFERENCED_PARAMETER(buffer_h);
+	UNREFERENCED_PARAMETER(swap_interval);
+	UNREFERENCED_PARAMETER(private_tag_h);
+	UNREFERENCED_PARAMETER(clip_rect_count);
+	UNREFERENCED_PARAMETER(clip_rect);
+
+	EMGD_TRACE_STUB;
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+
+} /* SwapToDCBuffer() */
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSwapToDCSystem()
+ * function.  This function causes a flip to the "system buffer" (a.k.a. frame
+ * buffer).
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param swap_chain_h (IN) The handle for this swap chain (an opaque pointer
+ * to a emgddc_swapchain_t).
+ * @return PVRSRV_OK or a PVRSRV_ERROR enum value.
+ */
+static PVRSRV_ERROR SwapToDCSystem(IMG_HANDLE device_h,
+	IMG_HANDLE swap_chain_h)
+{
+	emgddc_devinfo_t   *devinfo;
+	emgddc_swapchain_t *swap_chain;
+	unsigned long      lock_flags;
+
+	EMGD_TRACE_ENTER;
+	EMGD_DEBUG("device_h = 0x%p", device_h);
+
+
+	if (!device_h || !swap_chain_h) {
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	devinfo = (emgddc_devinfo_t *) device_h;
+	swap_chain = (emgddc_swapchain_t *) swap_chain_h;
+	if (!is_valid_swap_chain(devinfo, swap_chain, 1)) {
+		printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p) and/or "
+			"swap chain handle (0x%p)\n",__FUNCTION__, devinfo, swap_chain);
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	/* This must be a flip-able swap chain, or we can't cause a flip for it: */
+	if (!(swap_chain->flags & PVR2D_CREATE_FLIPCHAIN_OEMFLIPCHAIN)) {
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+
+	flush_flip_queue(swap_chain);
+	emgddc_flip(swap_chain, &devinfo->system_buffer);
+
+	spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+
+
+	EMGD_TRACE_EXIT;
+	return PVRSRV_OK;
+
+} /* SwapToDCSystem() */
+
+
+/**
+ * Drains the circular queue of buffers to flip for a specified swap chain.
+ * The queue is processed in order.  For every item in the queue, processing is
+ * as follows:
+ *
+ * - An item that has been "completed" (i.e. PVR services has been told that
+ *   the flip occured), but hasn't reached the end of its swap interval, is
+ *   immediately ended and cleared.
+ *
+ * - An item that has been flipped, but hasn't been "completed" with PVR
+ *   services, is "completed," ended, and cleared.
+ *
+ * - An item that has been queued, but hasn't been flipped, is immediately
+ *   flipped (i.e. given the Poulsbo hardware, this really means that the
+ *   hardware is told to flip them at the start of the next vertical blanking
+ *   period), "completed," ended, and cleared.
+ *
+ * Note: This function assumes that the calling function has already obtained
+ * the spin lock.
+ *
+ * @param swap_chain (IN) The swap chain to flush the queue for.
+ */
+static void flush_flip_queue(emgddc_swapchain_t *swap_chain)
+{
+	emgddc_flip_queue_item_t *flip_item;
+	unsigned long max_index;
+	unsigned long i;
+
+	EMGD_TRACE_ENTER;
+
+
+	/* Get the first item to drain in the circular queue: */
+	flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
+	max_index = swap_chain->buffer_count - 1;
+
+	for (i = 0 ; i < swap_chain->buffer_count ; i++) {
+		if (flip_item->valid == EMGD_FALSE) {
+			continue;
+		}
+
+		EMGD_DEBUG("Flushing buffer offset=0x%lx", flip_item->buffer->offset);
+
+		if ((swap_chain->devinfo->flipping_disabled == EMGD_FALSE) &&
+			(flip_item->flipped == EMGD_FALSE) &&
+			(swap_chain->valid == EMGD_TRUE)) {
+			EMGD_DEBUG("Flipping to buffer offset=0x%lx",
+				flip_item->buffer->offset);
+			emgddc_flip(swap_chain, flip_item->buffer);
+		}
+
+		if (flip_item->cmd_completed == EMGD_FALSE) {
+			PVRSRV_DC_DISP2SRV_KMJTABLE	*pvr_jtable = swap_chain->pvr_jtable;
+
+			EMGD_DEBUG("Calling pfnPVRSRVCmdComplete() for buffer offset=0x%lx",
+				flip_item->buffer->offset);
+			pvr_jtable->pfnPVRSRVCmdComplete(flip_item->cmd_complete, IMG_TRUE);
+		}
+
+		/* We're done with this item in the queue.  Prepare for processing the
+		 * next item:
+		 */
+		flip_item->flipped = EMGD_FALSE;
+		flip_item->cmd_completed = EMGD_FALSE;
+		flip_item->valid = EMGD_FALSE;
+
+		/* Point to the next item in the circular queue: */
+		swap_chain->remove_index++;
+		if (swap_chain->remove_index > max_index) {
+			swap_chain->remove_index = 0;
+		}
+
+		/* Get the next item in the circular queue: */
+		flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
+	}
+
+	/* Reset the circular queue to the start: */
+	swap_chain->insert_index = 0;
+	swap_chain->remove_index = 0;
+
+
+	EMGD_TRACE_EXIT;
+
+} /* flush_flip_queue() */
+
+
+static void set_flush_state_internal_nolock(emgddc_devinfo_t* devinfo,
+	emgd_bool flush_state)
+{
+	emgddc_swapchain_t *swap_chain = devinfo->flipable_swapchains;
+
+	EMGD_TRACE_ENTER;
+
+
+	if (flush_state) {
+		if (devinfo->set_flush_state_ref_count == 0) {
+			/* Don't actually disable interrupts.  Just set a flag so that
+			 * buffer flips won't be queued, then flush the circular buffer of
+			 * all pending flips, for all swap chains:
+			 */
+			devinfo->flush_commands = EMGD_TRUE;
+			while (swap_chain != NULL) {
+				flush_flip_queue(swap_chain);
+				swap_chain = swap_chain->next;
+			}
+		}
+		devinfo->set_flush_state_ref_count++;
+	} else {
+		if (devinfo->set_flush_state_ref_count != 0) {
+			devinfo->set_flush_state_ref_count--;
+			if (devinfo->set_flush_state_ref_count == 0) {
+				/* Don't actually enable interrupts.  Just set a flag so that
+				 * buffer flips will be queued:
+				 */
+				devinfo->flush_commands = EMGD_FALSE;
+			}
+		}
+	}
+
+
+	EMGD_TRACE_EXIT;
+}
+
+
+static void set_flush_state_external(emgddc_devinfo_t* devinfo,
+	emgd_bool flush_state)
+{
+	unsigned long lock_flags;
+
+	EMGD_TRACE_ENTER;
+
+
+	spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+
+	if (devinfo->flush_commands != flush_state) {
+		devinfo->flush_commands = flush_state;
+		set_flush_state_internal_nolock(devinfo, flush_state);
+	}
+
+	spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+
+
+	EMGD_TRACE_EXIT;
+}
+
+
+/**
+ * Implementation of the PVRSRV_DC_SRV2DISP_KMJTABLE.pfnSetDCState() function.
+ * This function is supposed to set some state flags in the driver, affecting
+ * interrupt-driven buffer flips.
+ *
+ * Note: The following function used to never be called, but now is called when
+ * X11 is rotated 90 degrees (it is called as a result of an interrupt handler
+ * dealing with an SGX hardware reset).  As such, the code that this calls
+ * cannot enable/disable interrupts (which may cause an interrupt handler to be
+ * registered/unregistered).
+ *
+ * Note: The code that this calls seems overly complicated.  If we never enable
+ * SUPPORT_FB_EVENTS, it can be simplified (e.g. no use of
+ * set_flush_state_ref_count).
+ *
+ * @param device_h (IN) The handle for this device (an opaque pointer to
+ * devinfo).
+ * @param state (IN) Either DC_STATE_FLUSH_COMMANDS or
+ * DC_STATE_NO_FLUSH_COMMANDS.
+ */
+static IMG_VOID SetDCState(IMG_HANDLE device_h, IMG_UINT32 state)
+{
+	emgddc_devinfo_t *devinfo = (emgddc_devinfo_t *) device_h;
+
+	EMGD_TRACE_ENTER;
+	EMGD_DEBUG("device_h = 0x%p", device_h);
+
+
+	if (!is_valid_devinfo((emgddc_devinfo_t *) device_h)) {
+		printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p)\n",
+			__FUNCTION__, device_h);
+		return;
+	}
+
+	switch (state) {
+	case DC_STATE_FLUSH_COMMANDS:
+		set_flush_state_external(devinfo, EMGD_TRUE);
+		break;
+	case DC_STATE_NO_FLUSH_COMMANDS:
+		set_flush_state_external(devinfo, EMGD_FALSE);
+		break;
+	default:
+		break;
+	}
+
+
+	EMGD_TRACE_EXIT;
+} /* SetDCState() */
+
+
+#ifdef SUPPORT_FB_EVENTS
+/* NOTE -- The following code is probably not correct.  It was inherited from
+ * an early IMG/UMG DDK, and has never been used.  If we ever decide to use
+ * this code, we should look at the latest DDK and UMG code, to glean what may
+ * be really needed.  At a minimum, the following code needs to affect all swap
+ * chains.
+ */
+
+static int emgddc_fb_events(struct notifier_block *notif,
+	unsigned long event, void *data)
+{
+	emgddc_devinfo_t *devinfo;
+	emgddc_swapchain_t *swap_chain;
+	struct fb_event *fb_event = (struct fb_event *) data;
+	emgd_bool blanked;
+	unsigned long lock_flags;
+
+	EMGD_TRACE_ENTER;
+
+
+	if (event != FB_EVENT_BLANK) {
+		return 0;
+	}
+
+	/* Look up the device (for DIH/Extended mode): */
+	if (notif == &(global_devinfo[0]->lin_notif_block)) {
+		devinfo = global_devinfo[0];
+	} else if (notif == &(global_devinfo[1]->lin_notif_block)) {
+		devinfo = global_devinfo[1];
+	} else {
+		printk(KERN_ERR "[EMGD] emgddc_fb_events() cannot find its device\n");
+		return -ENODEV;
+	}
+	swap_chain = devinfo->flipable_swapchains;
+
+	blanked = (*(IMG_INT *) fb_event->data != 0) ? EMGD_TRUE : EMGD_FALSE;
+
+	if (blanked != swap_chain->blanked) {
+		swap_chain->blanked = blanked;
+
+		spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+
+		if (blanked) {
+			set_flush_state_internal_nolock(devinfo, EMGD_TRUE);
+		} else {
+			set_flush_state_internal_nolock(devinfo, EMGD_FALSE);
+		}
+
+		spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+	return 0;
+}
+
+
+static emgd_error_t enable_event_notification(emgddc_devinfo_t *devinfo)
+{
+	int res;
+	emgddc_swapchain_t *swap_chain = devinfo->flipable_swapchains;
+
+	EMGD_TRACE_ENTER;
+
+
+	memset(&devinfo->lin_notif_block, 0, sizeof(devinfo->lin_notif_block));
+
+	devinfo->lin_notif_block.notifier_call = emgddc_fb_events;
+	swap_chain->blanked = EMGD_FALSE;
+	res = fb_register_client(&devinfo->lin_notif_block);
+	if (res != 0) {
+		EMGD_ERROR_EXIT("fb_register_client() failed (%d)", res);
+		return EMGD_ERROR_GENERIC;
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+	return EMGD_OK;
+}
+
+
+static emgd_error_t disable_event_notification(emgddc_devinfo_t *devinfo)
+{
+	int res;
+
+
+	EMGD_TRACE_ENTER;
+
+
+	res = fb_unregister_client(&devinfo->lin_notif_block);
+	if (res != 0) {
+		EMGD_ERROR_EXIT("fb_unregister_client() failed (%d)", res);
+		return EMGD_ERROR_GENERIC;
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+	return EMGD_OK;
+}
+#endif /* SUPPORT_FB_EVENTS */
+
+
+/**
+ * This function does per-vblank processing of the circular queue of buffers to
+ * flip.  It is called for each flip-able swap chain, during a VBlank
+ * interrupt.  The first item in the queue is processed, and if it is cleared
+ * (see below), the next item is processed, etc.  Items are processed as
+ * follows:
+ *
+ * - An item that hasn't been flipped, is flipped.  In this case, processing
+ *   stops.  It is assumed that the swap interval for this item is at least
+ *   one, and therefore, another vblank is needed for this flip.
+ *
+ * - An item that has been flipped, but hasn't been "completed" (i.e. PVR
+ *   services has been told that the flip occured), is "completed" and has its
+ *   swap interval decremented by 1.  If the swap interval is now 0, the item
+ *   is cleared, allowing processing of the next item to start.
+ *
+ * - An item that has been "completed," but hasn't reached the end of its swap
+ *   interval, has its swap interval decremented by 1.  If the swap interval is
+ *   now 0, the item is cleared, allowing processing of the next item to start.
+ *
+ * @param swap_chain (IN) The swap chain to process the queue for.
+ */
+emgd_bool emgddc_process_flip_queue_for_vblank(emgddc_swapchain_t *swap_chain)
+{
+	PVRSRV_DC_DISP2SRV_KMJTABLE	*pvr_jtable = swap_chain->pvr_jtable;
+	IMG_BOOL status = IMG_TRUE;
+	emgddc_flip_queue_item_t *flip_item;
+	unsigned long max_index;
+
+	EMGD_TRACE_ENTER;
+
+
+	if (swap_chain->devinfo->flush_commands) {
+		EMGD_TRACE_EXIT;
+		return status;
+	}
+
+	/* Get the first item to process in the circular queue: */
+	flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
+	max_index = swap_chain->buffer_count - 1;
+
+	while (flip_item->valid) {
+		if (flip_item->flipped) {
+			if (!flip_item->cmd_completed) {
+				EMGD_DEBUG("Calling pfnPVRSRVCmdComplete() for buffer "
+					"offset=0x%lx", flip_item->buffer->offset);
+				pvr_jtable->pfnPVRSRVCmdComplete(flip_item->cmd_complete,
+					IMG_TRUE);
+				flip_item->cmd_completed = EMGD_TRUE;
+			}
+
+			flip_item->swap_interval--;
+			EMGD_DEBUG("Swap interval is %lu for buffer offset=0x%lx",
+				flip_item->swap_interval, flip_item->buffer->offset);
+
+			if (flip_item->swap_interval == 0) {
+				/* We're done with this item in the queue.  Prepare for
+				 * processing the next item:
+				 */
+				flip_item->cmd_completed = EMGD_FALSE;
+				flip_item->flipped = EMGD_FALSE;
+				flip_item->valid = EMGD_FALSE;
+
+				/* Point to the next item in the circular queue: */
+				swap_chain->remove_index++;
+				if (swap_chain->remove_index > max_index) {
+					swap_chain->remove_index = 0;
+				}
+			} else {
+				/* Wait for more vblanks before doing more queue processing: */
+				break;
+			}
+		} else {
+			EMGD_DEBUG("Flipping to buffer offset=0x%lx",
+				flip_item->buffer->offset);
+			emgddc_flip(swap_chain, flip_item->buffer);
+			flip_item->flipped = EMGD_TRUE;
+			/* Wait for more vblanks before doing more queue processing: */
+			break;
+		}
+
+		/* Get the next item in the circular queue: */
+		flip_item = &swap_chain->flip_queue[swap_chain->remove_index];
+	}
+
+
+	EMGD_TRACE_EXIT;
+
+	return status;
+
+} /* emgddc_process_flip_queue_for_vblank() */
+
+
+/**
+ * This is called by a HAL-implemented, Linux interrupt handler.  It is called
+ * when a VBlank interrupt occurs.  All device-specific functionality was
+ * implemented by the HAL, and only 3DD-specific functionality needs to be
+ * provided by this function.
+ *
+ * @param pdevinfo (IN) Pointer to the devinfo that had a VBlank interrupt.
+ * @return Non-zero for success, zeron for failure.
+ */
+static int emgddc_process_vblank(void* pdevinfo)
+{
+	emgddc_devinfo_t *devinfo = (emgddc_devinfo_t *) pdevinfo;
+	emgddc_swapchain_t *swap_chain;
+	unsigned long lock_flags;
+
+	EMGD_TRACE_ENTER;
+
+
+	if ((devinfo != global_devinfo[0]) && (devinfo != global_devinfo[1])) {
+		return 0;
+	}
+
+	spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+
+	swap_chain = devinfo->flipable_swapchains;
+	while (swap_chain != NULL) {
+		(void) emgddc_process_flip_queue_for_vblank(swap_chain);
+		swap_chain = swap_chain->next;
+	}
+
+	spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+
+	return 1;
+
+} /* emgddc_process_vblank() */
+
+
+/**
+ * Called by PVR services to flip a buffer.  When interrupts are supported, the
+ * flip may be queued (in a circular buffer) to happen later.  When interrupts
+ * are not supported, the flip always happens immediately
+ *
+ * @param cmd_cookie_h (IN) An opaque pointer to a PVR service data structure
+ *   that must be handed back when the flip is "completed" (i.e. PVR services
+ *   is told that the flip occured).
+ * @param data_size (IN) Size of the flip command and all clipping rectangles
+ * (which isn't supported).  This is only used for consistency-checking.
+ * @param data (IN) A pointer to information about what to flip.
+ */
+static IMG_BOOL emgddc_process_flip(IMG_HANDLE cmd_cookie_h,
+	IMG_UINT32 data_size,
+	IMG_VOID *data)
+{
+	DISPLAYCLASS_FLIP_COMMAND *flip_cmd;
+	emgddc_devinfo_t *devinfo;
+	emgddc_buffer_t *buffers;
+	emgddc_swapchain_t *swap_chain;
+	unsigned long max_index;
+	emgddc_flip_queue_item_t* flip_item;
+	unsigned long lock_flags;
+	int must_flip = 0;
+	int must_complete = 0;
+	igd_context_t *context;
+
+	EMGD_TRACE_ENTER;
+
+
+	/*
+	 * Unpack the flip command and look for errors:
+	 */
+
+	if (!cmd_cookie_h || !data) {
+		EMGD_ERROR_EXIT("NULL parameter(s)");
+		return IMG_FALSE;
+	}
+
+	flip_cmd = (DISPLAYCLASS_FLIP_COMMAND *) data;
+
+	/* Note: the data_size actually accounts for both the flip command and
+	 * all of the clipping rectangles.  As such, the only error is if
+	 * data_size is smaller than the sizeof the flip command:
+	 */
+	if (flip_cmd == IMG_NULL ||
+		(sizeof(DISPLAYCLASS_FLIP_COMMAND) > data_size)) {
+		EMGD_ERROR_EXIT("Invalid flip_cmd (0x%p)", flip_cmd);
+		return IMG_FALSE;
+	}
+
+	devinfo = (emgddc_devinfo_t *) flip_cmd->hExtDevice;
+	buffers = (emgddc_buffer_t *) flip_cmd->hExtBuffer;
+	swap_chain = (emgddc_swapchain_t *) flip_cmd->hExtSwapChain;
+
+	if (!is_valid_swap_chain(devinfo, swap_chain, 1)) {
+		/* Note: Hardware video decode creates pixmap swap chains,
+		 * and when they are being destroyed (at
+		 * the end of video playback), something tries to flip these
+		 * non-flipable swap chains.  The only way to avoid a hang is to
+		 * "complete" the flip command.
+		 */
+		printk(KERN_ERR "[EMGD] %s() given invalid device handle (0x%p) and/or "
+			"swap chain handle (0x%p)\n",__FUNCTION__, devinfo, swap_chain);
+		swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h, IMG_TRUE);
+		EMGD_TRACE_EXIT;
+		return IMG_TRUE;
+	}
+
+	spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+
+	if ((devinfo->flipping_disabled == EMGD_TRUE) ||
+		(swap_chain->valid != EMGD_TRUE)) {
+		/* We won't flip, but must tell PVR services that the flip occured: */
+		EMGD_DEBUG("Something (e.g. a mode change) has invalidated\n"
+			"this swap chain.  As such buffer flips are not allowed.\n"
+			"If a mode change caused this problem, this swap chain\n"
+			"needs to be destroyed, and a new one created.");
+		swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h, IMG_TRUE);
+		spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+		EMGD_TRACE_EXIT;
+		return IMG_TRUE;
+	}
+
+	context = devinfo->priv->context;
+	if (context->device_context.power_state != IGD_POWERSTATE_D0) {
+		/* If device is in a suspended state, but PVR services asks the driver
+		 * to perform a buffer flip, basically ignore it except for telling PVR
+		 * services that we did the flip:
+		 */
+		EMGD_DEBUG("Device in suspended state--completing command");
+		swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h, IMG_TRUE);
+		spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+		EMGD_TRACE_EXIT;
+		return IMG_TRUE;
+	}
+
+	/* Get the first item to add to the circular queue: */
+	flip_item = &swap_chain->flip_queue[swap_chain->insert_index];
+	max_index = swap_chain->buffer_count - 1;
+
+
+	/*
+	 * Decide what needs to be done:
+	 */
+	if ((flip_cmd->ui32SwapInterval == 0) ||
+		(devinfo->flush_commands == EMGD_TRUE)) {
+		/* Perform and complete the flip now: */
+		must_flip = 1;
+		must_complete = 1;
+	} else {
+		/* PVR services only calls emgddc_process_flip() when the 3DD completes
+		 * the previous flip.  Thus, the circular flip_item queue should never
+		 * overflow.  However, just in case, check whether the flip_item
+		 * already contains a valid/queued flip (i.e. we've overflowed the
+		 * circular queue).
+		 */
+		if (flip_item->valid == EMGD_FALSE) {
+			if (swap_chain->insert_index == swap_chain->remove_index) {
+			/* Perform the flip now, but queue it for completion: */
+				must_flip = 1;
+			}
+			/* else - queue the flip for later: */
+		} else {
+			/* Just in case we overflow the circular queue, generate an error */
+			swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h,IMG_TRUE);
+			spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+			EMGD_ERROR_EXIT("Overflowed the circular flip_item queue");
+			return IMG_FALSE;
+		}
+	}
+
+
+	/*
+	 * Do what needs to be done:
+	 */
+	if (must_flip) {
+		/* Perform the flip now: */
+		EMGD_DEBUG("Flipping to buffer offset=0x%lx", buffers->offset);
+		emgddc_flip(swap_chain, buffers);
+	}
+	if (must_complete) {
+		/* Tell the PVR services that the flip occured: */
+		EMGD_DEBUG("Calling pfnPVRSRVCmdComplete() for buffer offset=0x%lx",
+			buffers->offset);
+		swap_chain->pvr_jtable->pfnPVRSRVCmdComplete(cmd_cookie_h,IMG_TRUE);
+	} else {
+		/* Queue the flip for later completion: */
+		EMGD_DEBUG("Queueing buffer offset=0x%lx", buffers->offset);
+		if (must_flip) {
+			flip_item->flipped = EMGD_TRUE;
+		}
+		flip_item->cmd_complete = cmd_cookie_h;
+		flip_item->swap_interval = (unsigned long) flip_cmd->ui32SwapInterval;
+		flip_item->valid = EMGD_TRUE;
+		flip_item->buffer = buffers;
+
+		swap_chain->insert_index++;
+		if (swap_chain->insert_index > max_index) {
+			swap_chain->insert_index = 0;
+		}
+	}
+
+	spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+
+	EMGD_TRACE_EXIT;
+	return IMG_TRUE;
+} /* emgddc_process_flip() */
+
+
+/**
+ * For a given devinfo, unmap's the frame buffer, and frees the devinfo and
+ * it's surfaces.
+ *
+ * @param dev (IN) The drm_device for this driver connection.
+ */
+void emgddc_free_a_devinfo(emgddc_devinfo_t *devinfo)
+{
+	igd_context_t *context = devinfo->priv->context;
+
+	EMGD_TRACE_ENTER;
+
+	if (devinfo->priv->hal_running) {
+		/* Un-register (if needed) the interrupt connection with the HAL: */
+		if (devinfo->interrupt_h) {
+			context->dispatch.unregister_vblank_callback(devinfo->interrupt_h);
+			devinfo->interrupt_h = NULL;
+		}
+
+		if (devinfo->system_buffer.virt_addr) {
+			context->dispatch.gmm_unmap(devinfo->system_buffer.virt_addr);
+		}
+	}
+	OS_FREE(devinfo);
+
+	EMGD_TRACE_EXIT;
+} /* emgddc_free_a_devinfo() */
+
+
+/**
+ * Frees all devinfo structures and their surfaces.  This is called during
+ * de-init time, or when init fails.
+ */
+void emgddc_free_all_devinfos(void)
+{
+	emgddc_devinfo_t *devinfo;
+
+	EMGD_TRACE_ENTER;
+
+	/* Free the primary display's structures: */
+	devinfo = global_devinfo[0];
+	emgddc_free_a_devinfo(devinfo);
+	global_devinfo[0] = NULL;
+
+	/* Free the secondary display's structures, if applicable: */
+	if (NULL == (devinfo = global_devinfo[1])) {
+		emgddc_free_a_devinfo(devinfo);
+		global_devinfo[1] = NULL;
+	}
+
+	EMGD_TRACE_EXIT;
+} /* emgddc_free_all_devinfos() */
+
+
+/**
+ * Initialize the "static" (i.e. doesn't vary with alter_display) portion of
+ * a devinfo structure.
+ *
+ * @param dev (IN) The drm_device for this driver connection.
+ * @param devinfo (IN/OUT) The devinfo to initialize.
+ * @param port_number (IN) Which devinfo (0 for primary, 1 for secondary/DIH).
+ * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
+ */
+static emgd_error_t emgddc_init_devinfo(struct drm_device *dev,
+	emgddc_devinfo_t *devinfo, int which_devinfo)
+{
+	drm_emgd_priv_t *priv = dev->dev_private;
+	PVRSRV_DC_DISP2SRV_KMJTABLE	*pvr_jtable;
+	PFN_CMD_PROC cmd_proc_list[EMGDDC_COMMAND_COUNT];
+	IMG_UINT32 sync_count_list[EMGDDC_COMMAND_COUNT][2];
+
+	EMGD_TRACE_ENTER;
+
+
+	/*
+	 * Initialize the static/display-independent devinfo values:
+	 */
+	devinfo->which_devinfo = which_devinfo;
+	devinfo->priv = priv;
+	devinfo->drm_device = dev;
+	devinfo->flipable_swapchains = NULL;
+	devinfo->swap_chain_id_counter = 0;
+	devinfo->display_info.ui32MaxSwapChainBuffers = 5;
+	devinfo->display_info.ui32MaxSwapChains = 1024 * 1024;
+	/* Note: change from zero if we support interrupts and see the need: */
+	devinfo->display_info.ui32MaxSwapInterval = 2;
+	devinfo->display_info.ui32MinSwapInterval = 0;
+	EMGD_DEBUG("Maximum number of swap chains: %lu",
+		devinfo->display_info.ui32MaxSwapChains);
+	EMGD_DEBUG("Maximum number of swap chain buffers: %lu",
+		devinfo->display_info.ui32MaxSwapChainBuffers);
+	strncpy(devinfo->display_info.szDisplayName, DISPLAY_DEVICE_NAME,
+		MAX_DISPLAY_NAME_SIZE);
+	devinfo->flush_commands = EMGD_FALSE;
+	spin_lock_init(&devinfo->swap_chain_lock);
+
+
+	/*
+	 * Get the PVR services jump table, which this 3rd-party display driver can
+	 * use to call PVR services:
+	 */
+	if (!PVRGetDisplayClassJTable(&devinfo->pvr_jtable)) {
+		EMGD_ERROR_EXIT("Can not get PVR services jump table");
+		return EMGD_ERROR_INIT_FAILURE;
+	}
+	pvr_jtable = &devinfo->pvr_jtable;
+
+
+	/*
+	 * Setup the jump table that PVR services uses to call this 3rd-party
+	 * display driver:
+	 */
+	devinfo->dc_jtable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
+	devinfo->dc_jtable.pfnOpenDCDevice = OpenDCDevice;
+	devinfo->dc_jtable.pfnCloseDCDevice = CloseDCDevice;
+	devinfo->dc_jtable.pfnEnumDCFormats = EnumDCFormats;
+	devinfo->dc_jtable.pfnEnumDCDims = EnumDCDims;
+	devinfo->dc_jtable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
+	devinfo->dc_jtable.pfnGetDCInfo = GetDCInfo;
+	devinfo->dc_jtable.pfnGetBufferAddr = GetDCBufferAddr;
+	devinfo->dc_jtable.pfnCreateDCSwapChain = CreateDCSwapChain;
+	devinfo->dc_jtable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
+	devinfo->dc_jtable.pfnSetDCDstRect = SetDCDstRect;
+	devinfo->dc_jtable.pfnSetDCSrcRect = SetDCSrcRect;
+	devinfo->dc_jtable.pfnSetDCDstColourKey = SetDCDstColourKey;
+	devinfo->dc_jtable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
+	devinfo->dc_jtable.pfnGetDCBuffers = GetDCBuffers;
+	devinfo->dc_jtable.pfnSwapToDCBuffer = SwapToDCBuffer;
+	devinfo->dc_jtable.pfnSwapToDCSystem = SwapToDCSystem;
+	devinfo->dc_jtable.pfnSetDCState = SetDCState;
+
+
+	/*
+	 * Register this device with PVR services:
+	 */
+	if (pvr_jtable->pfnPVRSRVRegisterDCDevice(&devinfo->dc_jtable,
+		&devinfo->device_id ) != PVRSRV_OK) {
+		EMGD_ERROR_EXIT("Device registration failed");
+		return EMGD_ERROR_DEVICE_REGISTER_FAILED;
+	}
+
+	EMGD_DEBUG("Device ID: %d", (int)devinfo->device_id);
+
+
+	/*
+	 * Tell PVR services about the function to process swap-chain buffer
+	 * flips:
+	 */
+	cmd_proc_list[DC_FLIP_COMMAND] = emgddc_process_flip;
+
+	/* FIXME:  Not sure what these are for: */
+	sync_count_list[DC_FLIP_COMMAND][0] = 0; 
+	sync_count_list[DC_FLIP_COMMAND][1] = 2; 
+
+	if (pvr_jtable->pfnPVRSRVRegisterCmdProcList(devinfo->device_id,
+		&cmd_proc_list[0],
+		sync_count_list,
+		EMGDDC_COMMAND_COUNT) != PVRSRV_OK) {
+		EMGD_ERROR_EXIT("Can't register callback\n");
+		return EMGD_ERROR_CANT_REGISTER_CALLBACK;
+	}
+
+
+	EMGD_TRACE_EXIT;
+	return EMGD_OK;
+
+} /* emgddc_init_devinfo() */
+
+
+/** 
+ * Initializes the display/device-specific values of the devinfo structure for
+ * a specified display (primary or secondary).  This function is called during
+ * initialization time, and whenever the EMGD driver does a potential mode
+ * change, via alter_displays().
+ *
+ * @param devinfo (IN/OUT) The devinfo to initialize for the display.
+ * @param display (IN) The specified display (primary or secondary).
+ * @param port_number (IN) The port number of the specified display.
+ * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
+ */
+static emgd_error_t init_display(emgddc_devinfo_t *devinfo,
+	igd_display_h display,
+	unsigned short port_number)
+{
+	drm_emgd_priv_t *priv = devinfo->priv;
+	igd_context_t *context = priv->context;
+	unsigned long dc = priv->dc;
+	igd_framebuffer_info_t fb_info;
+	DISPLAY_FORMAT *display_format_list;
+	igd_display_info_t pt_info;
+	unsigned long *fb_list_pfs;
+	DISPLAY_DIMS *display_dim_list;
+	igd_display_info_t *mode_list = NULL;
+	igd_display_info_t *mode;
+	int mode_flags = IGD_QUERY_LIVE_MODES;
+	emgddc_buffer_t *buffer = &(devinfo->system_buffer);
+	int i = 1, j, ret;
+
+	EMGD_TRACE_ENTER;
+
+	EMGD_DEBUG("Parameters:");
+	EMGD_DEBUG(" devinfo=0x%p", devinfo);
+	EMGD_DEBUG(" devinfo->which_devinfo=%d", devinfo->which_devinfo);
+	EMGD_DEBUG(" display=0x%p", display);
+	EMGD_DEBUG(" port_number=%u", port_number);
+
+	/* Clear the following lists, in case we are re-initializing: */
+	OS_MEMSET(devinfo->display_format_list, 0,
+			sizeof(devinfo->display_format_list));
+	OS_MEMSET(devinfo->display_dim_list, 0,
+			sizeof(devinfo->display_dim_list));
+	display_format_list = devinfo->display_format_list;
+	display_dim_list = devinfo->display_dim_list;
+
+
+	/* Call get_display() to get some of the following info: */
+	ret = context->dispatch.get_display(display, port_number,
+		&fb_info, &pt_info, 0);
+	if (0 != ret) {
+		EMGD_ERROR_EXIT("get_display() returned %d", ret);
+		return EMGD_ERROR_GENERIC;
+	}
+
+
+	/*
+	 * Obtain the following addresses:
+	 *
+	 * - buffer->offset = Framebuffer GTT address
+	 * - virt_addr = gmm_map(framebuffer offset);
+	 */
+	buffer->offset = fb_info.fb_base_offset;
+	if(NULL == buffer->virt_addr){
+		buffer->virt_addr = context->dispatch.gmm_map(fb_info.fb_base_offset);
+	}
+	EMGD_DEBUG("buffer->virt_addr = 0x%p", buffer->virt_addr);
+	/* This is the offset of the allocated framebuffer (e.g. the
+	 * 1024x768 surface of gmm-managed memory):
+	 */
+	EMGD_DEBUG("fb_info->fb_base_offset = 0x%lx", fb_info.fb_base_offset);
+
+
+	/* Register (if we haven't) with the HAL to be able to use interrupts: */
+	if (!devinfo->interrupt_h) {
+		devinfo->interrupt_h =
+			context->dispatch.register_vblank_callback(emgddc_process_vblank,
+				devinfo, port_number);
+		if (!devinfo->interrupt_h) {
+			/* This should not happen, but just in case, provide an error: */
+			printk(KERN_ERR "Cannot establish the ability to perform VBlank "
+				"interrupts for port number %u.", port_number);
+		}
+	}
+
+
+	/*
+	 * Obtain and translate pixel formats:
+	 */
+	/* Note: We always care about the current pixel format: */
+	devinfo->emgd_pf = fb_info.pixel_format;
+	devinfo->pvr_pf = emgd2pvr_pf(fb_info.pixel_format);
+	display_format_list[0].pixelformat = emgd2pvr_pf(fb_info.pixel_format);
+	EMGD_DEBUG("FB's native EMGD pixel format = 0x%08lx", devinfo->emgd_pf);
+	EMGD_DEBUG("FB's PVR pixel format = %u",display_format_list[0].pixelformat);
+	if (!priv->xserver_running) {
+		/* In addition, provide an entire list of pixel formats: */
+		ret = context->dispatch.get_pixelformats(display, &fb_list_pfs, NULL,
+			NULL, NULL, NULL);
+		if (0 != ret) {
+			EMGD_ERROR_EXIT("get_pixelformats() returned %d", ret);
+			return EMGD_ERROR_GENERIC;
+		}
+		while (*fb_list_pfs) {
+			if ((devinfo->pvr_pf != emgd2pvr_pf(*fb_list_pfs)) &&
+				(PVRSRV_PIXEL_FORMAT_UNKNOWN != emgd2pvr_pf(*fb_list_pfs))) {
+				display_format_list[i].pixelformat = emgd2pvr_pf(*fb_list_pfs);
+				EMGD_DEBUG("  Add'l (%d) PVR pixel format = "
+					"%u", i, emgd2pvr_pf(*fb_list_pfs));
+			}
+			fb_list_pfs++;
+			if (++i >= EMGDDC_MAXFORMATS) {
+				/* Don't write past the end of the array */
+				EMGD_ERROR("Reached end of display_format_list!  Consider "
+						"increasing EMGDDC_MAXFORMATS.");
+				break;
+			}
+		}
+	}
+	devinfo->num_formats = i;
+	EMGD_DEBUG("Total number of translated pixel formats = %d", i);
+
+
+	/*
+	 * Obtain the possible dimensions, from the EMGD modes:
+	 */
+	/* Note: we always care about the current dimensions: */
+	devinfo->width = fb_info.width;
+	devinfo->height = fb_info.height;
+	devinfo->byte_stride = fb_info.screen_pitch;
+	EMGD_DEBUG("FB's width = %ld, height = %ld, stride = %ld",
+		devinfo->width, devinfo->height, devinfo->byte_stride);
+	display_dim_list[0].ui32Width = fb_info.width;
+	display_dim_list[0].ui32Height = fb_info.height;
+	display_dim_list[0].ui32ByteStride = fb_info.screen_pitch;
+	i = 1;
+	if (!priv->xserver_running) {
+		/* In addition, provide an entire list of dimensions: */
+		ret = context->dispatch.query_mode_list((igd_driver_h) context, dc,
+			&mode_list, mode_flags);
+		if (0 != ret) {
+			EMGD_ERROR_EXIT("query_mode_list() returned %d", ret);
+			return EMGD_ERROR_GENERIC;
+		}
+		mode = mode_list;
+		while (mode && (mode->width != IGD_TIMING_TABLE_END)) {
+			int seen = 0;
+			for (j = i - 1 ; j >= 0 ; j--) {
+				if ((display_dim_list[j].ui32Width == mode->width) &&
+					(display_dim_list[j].ui32Height == mode->height)) {
+					seen = 1;
+				}
+			}
+			if (!seen) {
+				display_dim_list[i].ui32Width = mode->width;
+				display_dim_list[i].ui32Height = mode->height;
+				display_dim_list[i].ui32ByteStride =
+					(mode->width * IGD_PF_BPP(devinfo->emgd_pf) + 7) >>3;
+				EMGD_DEBUG("  Add'l width = %d, height = %d, stride = %ld",
+					mode->width, mode->height,
+					display_dim_list[i].ui32ByteStride);
+				if (++i >= EMGDDC_MAXDIMS) {
+					/* Don't write past the end of the array */
+					EMGD_ERROR("Reached end of display_dim_list!  Consider "
+							"increasing EMGDDC_MAXDIMS.");
+					break;
+				}
+			}
+			mode++;
+		}
+	}
+	devinfo->num_dims = i;
+	EMGD_DEBUG("Total number of dimensions = %d", i);
+
+
+	/*
+	 * Obtain the size of the frame buffer, which will also be the size of any
+	 * swap chain buffers:
+	 */
+	devinfo->fb_size = devinfo->height * devinfo->byte_stride;
+	EMGD_DEBUG("Frame buffer size = %lu = %luMB = 0x%lx", devinfo->fb_size,
+		devinfo->fb_size / (1024 * 1024), devinfo->fb_size);
+
+
+	/*
+	 * Initialize the igd_surface_t structure for the frame buffer, in order
+	 * allow the buffer flipping code to flip back to the frame buffer:
+	 */
+	buffer->priv = priv;
+	buffer->offset = fb_info.fb_base_offset;
+	buffer->pitch = devinfo->byte_stride;
+	buffer->width = devinfo->width;
+	buffer->height = devinfo->height;
+	buffer->pixel_format = fb_info.pixel_format;
+	buffer->size = devinfo->fb_size;
+
+
+	EMGD_TRACE_EXIT;
+	return EMGD_OK;
+
+} /* init_display() */
+
+/** 
+ * Loops through the avaiable displays, invalidating the  associated flip-chains
+ * This function is called from igd_alter_displays so as to resolve any race 
+ * conditions that may occur due to performing a flip during a mode-set.
+ *
+ * @param display     (IN) The display whose flipchains are to be invalidated.
+ */
+static int emgddc_invalidate_flip_chains(int display) {
+
+	emgddc_devinfo_t * devinfo;
+	emgddc_swapchain_t *swap_chain;
+	unsigned long lock_flags;
+	igd_surface_t surf;
+	igd_display_h display_handle;
+	igd_context_t *context;
+	int i;
+	int ret;
+
+	EMGD_TRACE_ENTER;
+	EMGD_DEBUG("Parameters:");
+	EMGD_DEBUG("display=0x%1x",display);
+
+	for (i = 0; i < MAX_DISPLAYS; i++) {
+		if (display & (1 << i)) {
+			devinfo = global_devinfo[i];
+
+			if (devinfo == NULL) {
+				EMGD_DEBUG("Skipping NULL display at index %d", i);
+				continue;
+			}
+
+
+			/* Mode changes invalidate flip-able swap chains.  We can't destroy
+			 * them behind the back of PVR services, but we can and should
+			 * ignore all pending and future buffer flips for existing swap
+			 * chains.
+			 * Note: new swap chains will be valid, and be able to perform flips.
+			 */
+			/* Obtain the lock, to hold-off future interrupt handling for a bit */
+			spin_lock_irqsave(&devinfo->swap_chain_lock, lock_flags);
+			swap_chain = devinfo->flipable_swapchains;
+			while (swap_chain != NULL) {
+				swap_chain->valid = EMGD_FALSE;
+
+				flush_flip_queue(swap_chain);
+				swap_chain = swap_chain->next;
+			}
+			/* Now that we've invalidated pending flips, release the lock */
+			spin_unlock_irqrestore(&devinfo->swap_chain_lock, lock_flags);
+
+			/* Reset the frame-buffer information to point to the system
+			 * buffer */
+			context = devinfo->priv->context;
+			display_handle = (devinfo->which_devinfo == 1)?
+								devinfo->priv->secondary:devinfo->priv->primary;
+
+			surf.offset = devinfo->system_buffer.offset;
+			surf.pitch = devinfo->system_buffer.pitch;
+			surf.width = devinfo->system_buffer.width;
+			surf.height = devinfo->system_buffer.height;
+			surf.pixel_format = devinfo->system_buffer.pixel_format;
+			surf.flags = IGD_SURFACE_RENDER | IGD_SURFACE_DISPLAY;
+
+			ret = context->dispatch.set_surface(display_handle,
+					IGD_PRIORITY_NORMAL, IGD_BUFFER_DISPLAY, &surf, NULL, 0);
+
+			if (ret) {
+				EMGD_ERROR("set_surface() returned %d for display at index %d",
+						ret, i);
+			}
+		}
+	}
+
+	EMGD_TRACE_EXIT;
+
+	return 0;
+}
+
+
+/**
+ * [Re-]Initializes the 3DD's display/device-specific values for both devinfo
+ * structures.  This function is called during initializatio time, and whenever
+ * the EMGD driver does a potential mode change, via alter_displays().
+ *
+ * @param dev (IN) The drm_device associated with this driver.
+ * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
+ */
+static int emgddc_reinit_3dd(struct drm_device *dev)
+{
+	emgddc_devinfo_t *devinfo;
+	drm_emgd_priv_t *priv = dev->dev_private;
+	int ret;
+
+	EMGD_TRACE_ENTER;
+
+	if (0 == priv->dc) {
+		EMGD_DEBUG("not ready to re-init, because no dc has been set");
+		if (!priv->hal_running) {
+			/* Ensure that devinfo->interrupt_h is NULL: */
+			if (NULL != (devinfo = global_devinfo[0])) {
+				devinfo->interrupt_h = NULL;
+			}
+			if (NULL != (devinfo = global_devinfo[1])) {
+				devinfo->interrupt_h = NULL;
+			}
+		}
+		return EMGD_OK;
+	}
+
+	EMGD_DEBUG("The DC is 0x%08lx", priv->dc);
+	EMGD_DEBUG("IGD_DC_CLONE(priv->dc) is %d", IGD_DC_CLONE(priv->dc));
+	EMGD_DEBUG("IGD_DC_EXTENDED(priv->dc) is %d", IGD_DC_EXTENDED(priv->dc));
+
+	/* Always initialize the primary devinfo: */
+	ret = init_display(global_devinfo[0], priv->primary,
+		priv->primary_port_number);
+	if (ret != EMGD_OK) {
+		return ret;
+	}
+
+	/* Initialize the secondary devinfo if we're in DIH/extended mode: */
+	if (IGD_DC_EXTENDED(priv->dc)) {
+		EMGD_DEBUG("Detected that we're in DIH/EXTENDED mode");
+
+		/* Allocate the devinfo if it hasn't already been allocated: */
+		if (NULL == (devinfo = global_devinfo[1])) {
+			EMGD_DEBUG("Allocating devinfo structure for DIH/EXTENDED mode");
+			devinfo = (emgddc_devinfo_t *) OS_ALLOC(sizeof(emgddc_devinfo_t));
+			if (!devinfo) {
+				EMGD_ERROR_EXIT("Can not allocate emgddc_devinfo_t structure");
+				return EMGD_ERROR_OUT_OF_MEMORY;
+			}
+			OS_MEMSET(devinfo, 0, sizeof(emgddc_devinfo_t));
+
+			/* Perform static/display-independent initialization: */
+			ret = emgddc_init_devinfo(dev, devinfo, 1);
+			if (ret != EMGD_OK) {
+				EMGD_ERROR_EXIT("CAN NOT support DIH/EXTENDED mode!");
+				emgddc_free_a_devinfo(devinfo);
+				return ret;
+			}
+		}
+
+		/* Perform dynamic/display-dependent initialization: */
+		ret = init_display(devinfo, priv->secondary,
+			priv->secondary_port_number);
+		if (ret != EMGD_OK) {
+			EMGD_ERROR_EXIT("CAN NOT support DIH/EXTENDED mode!");
+			emgddc_free_a_devinfo(devinfo);
+			global_devinfo[1] = NULL;
+			return ret;
+		}
+
+		/* Remember the devinfo, for other functions that aren't passed it: */
+		global_devinfo[1] = devinfo;
+	}
+
+
+	EMGD_TRACE_EXIT;
+	return EMGD_OK;
+
+} /* emgddc_reinit_3dd() */
+
+
+/**
+ * Master initialization function.  This is called when the EMGD DRM module
+ * tells PVR services to start, which calls this function.
+ *
+ * @param dev (IN) The drm_device for this driver connection.
+ * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
+ */
+emgd_error_t emgddc_init(struct drm_device *dev)
+{
+	emgddc_devinfo_t *devinfo;
+	drm_emgd_priv_t *priv = dev->dev_private;
+	int ret;
+
+	EMGD_TRACE_ENTER;
+
+
+	/* Exit early if trying to initialize again: */
+	devinfo = global_devinfo[0];
+	if (devinfo != NULL) {
+		EMGD_TRACE_EXIT;
+		return EMGD_OK;
+	}
+
+	/* Always allocate the primary display's devinfo structure: */
+	devinfo = (emgddc_devinfo_t *) OS_ALLOC(sizeof(emgddc_devinfo_t));
+	if (!devinfo) {
+		EMGD_ERROR_EXIT("Can not allocate emgddc_devinfo_t structure");
+		return EMGD_ERROR_OUT_OF_MEMORY;
+	}
+	OS_MEMSET(devinfo, 0, sizeof(emgddc_devinfo_t));
+	global_devinfo[0] = devinfo;
+
+	/* Perform static/display-independent initialization: */
+	ret = emgddc_init_devinfo(dev, devinfo, 0);
+	if (ret != EMGD_OK) {
+		emgddc_free_all_devinfos();
+		return ret;
+	}
+
+	/* Perform dynamic/display-dependent initialization (if we're in
+	 * DIH/Extended mode, the secondary devinfo will also be allocated and
+	 * initialized):
+	 */
+	priv->reinit_3dd = emgddc_reinit_3dd;
+
+	/* Used inside igd_alter_displays */
+	priv->invalidate_flip_chains = emgddc_invalidate_flip_chains;
+
+	ret = emgddc_reinit_3dd(dev);
+	if (ret != EMGD_OK) {
+		emgddc_free_all_devinfos();
+		return ret;
+	}
+
+	/* Remember the devinfo, for other functions that aren't passed it: */
+	global_devinfo[0] = devinfo;
+
+
+	EMGD_TRACE_EXIT;
+	return EMGD_OK;
+
+} /* emgddc_init() */
+
+
+/**
+ * Master de-initialization function.  This is called when the EMGD DRM module
+ * is being unloaded (it tells PVR services to exit, which calls this
+ * function).
+ *
+ * @return emgd_error_t value (e.g. EMGD_OK, EMGD_ERROR_OUT_OF_MEMORY).
+ */
+emgd_error_t emgddc_deinit(void)
+{
+	emgddc_devinfo_t *devinfo;
+	int i;
+	emgd_error_t ret = EMGD_OK;
+
+	EMGD_TRACE_ENTER;
+
+
+	for (i = 0 ; i < 2 ; i++) {
+		devinfo = global_devinfo[i];
+		if (devinfo == NULL) {
+			continue;
+		}
+
+
+		/* Unhook and unregister from PVR services: */
+		if (devinfo->pvr_jtable.pfnPVRSRVRemoveCmdProcList(devinfo->device_id,
+			EMGDDC_COMMAND_COUNT) != PVRSRV_OK) {
+			ret = EMGD_ERROR_GENERIC;
+		}
+		if (devinfo->pvr_jtable.pfnPVRSRVRemoveDCDevice(devinfo->device_id) !=
+			PVRSRV_OK) {
+			ret = EMGD_ERROR_GENERIC;
+		}
+
+
+		/* Delete any/all swap chains now: */
+		/* Note: If we ever support interrupts, there may be a race condition
+		 * of pending flips.  This was placed here, after the PVR services
+		 * thinks the driver has gone away, so that no flips should come by
+		 * this time.
+		 */
+		while (devinfo->flipable_swapchains) {
+			if (PVRSRV_OK != DestroyDCSwapChain(devinfo,
+				devinfo->flipable_swapchains)) {
+				ret = EMGD_ERROR_GENERIC;
+			}
+		}
+		while (devinfo->pixmap_swapchains) {
+			if (PVRSRV_OK != DestroyDCSwapChain(devinfo,
+				devinfo->pixmap_swapchains)) {
+				ret = EMGD_ERROR_GENERIC;
+			}
+		}
+
+
+		emgddc_free_a_devinfo(devinfo);
+		global_devinfo[i] = NULL;
+	}
+
+
+	EMGD_TRACE_EXIT;
+	return ret;
+
+} /* emgddc_deinit() */
+
+
+/*
+ * Potentially perform a mode change.
+ *
+ * If the X server is running, PVR services (including this function) can't
+ * do mode changes.  To avoid having to switch modes, ensure that the
+ * current pixel format and dimension is specified:
+ *
+ * If the X server is NOT running, PVR services (including this function)
+ * can do mode changes.  In this case, if the pixel format and/or
+ * dimensions don't match the current mode, perform a mode change (as long
+ * as valid values are provided):
+ */
+static PVRSRV_ERROR do_mode_change(igd_context_t *context,
+		emgddc_devinfo_t *devinfo,
+		drm_emgd_priv_t *priv,
+		DISPLAY_SURF_ATTRIBUTES *dst_surf_attrib)
+{
+	struct drm_device* drm_dev;
+	int err = PVRSRV_OK;
+
+	drm_dev = devinfo->drm_device;
+
+	if (priv->xserver_running) {
+		if ((dst_surf_attrib->pixelformat != devinfo->pvr_pf) ||
+			(dst_surf_attrib->sDims.ui32ByteStride != devinfo->byte_stride) ||
+			(dst_surf_attrib->sDims.ui32Width != devinfo->width) ||
+			(dst_surf_attrib->sDims.ui32Height != devinfo->height)) {
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+	} else if ((dst_surf_attrib->pixelformat != devinfo->pvr_pf) ||
+			(dst_surf_attrib->sDims.ui32ByteStride != devinfo->byte_stride)||
+			(dst_surf_attrib->sDims.ui32Width != devinfo->width) ||
+			(dst_surf_attrib->sDims.ui32Height != devinfo->height)) {
+		unsigned long emgd_pf = pvr2emgd_pf(dst_surf_attrib->pixelformat);
+		igd_display_info_t *mode_list = NULL;
+		igd_display_info_t *mode = NULL;
+		igd_display_info_t *desired_mode = NULL;
+		int mode_flags = IGD_QUERY_LIVE_MODES;
+		unsigned long byte_stride;
+		igd_framebuffer_info_t primary_fb_info;
+		igd_framebuffer_info_t secondary_fb_info;
+		igd_display_h primary;
+		igd_display_h secondary;
+
+		printk("[EMGD] A mode change is requested.  The following new values\n"
+			"[EMGD] will be checked, and if good, take effect:\n");
+		printk("[EMGD]   pixel format = %u (PVR) = 0x%08lx (EMGD)\n",
+			dst_surf_attrib->pixelformat, emgd_pf);
+		printk("[EMGD]   width = %lu, height = %lu\n",
+			dst_surf_attrib->sDims.ui32Width,
+			dst_surf_attrib->sDims.ui32Height);
+		printk("[EMGD]   stride = %lu\n",dst_surf_attrib->sDims.ui32ByteStride);
+
+
+		/* Check the pixel format: */
+		if (IGD_PF_UNKNOWN == emgd_pf) {
+			printk(KERN_ERR "Unknown pixel format %u\n",
+				dst_surf_attrib->pixelformat);
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+
+
+		/* Check the width, height, and stride: */
+		EMGD_DEBUG("Calling query_mode_list()");
+		err = context->dispatch.query_mode_list(context, priv->dc,
+			&mode_list, mode_flags);
+		if (err) {
+			printk(KERN_ERR "The query_mode_list() function returned %d.", err);
+			return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+		}
+		EMGD_DEBUG("Comparing the mode list with the desired width, height, "
+				"and stride...");
+		mode = mode_list;
+		while (mode && (mode->width != IGD_TIMING_TABLE_END)) {
+			byte_stride =  IGD_PF_PIXEL_BYTES(emgd_pf, mode->width);
+			EMGD_DEBUG(" ... Found a mode with width=%d, height=%d, "
+					"refresh=%d;", mode->width, mode->height, mode->refresh);
+			if ((mode->width == dst_surf_attrib->sDims.ui32Width) &&
+				(mode->height == dst_surf_attrib->sDims.ui32Height) &&
+				(byte_stride == dst_surf_attrib->sDims.ui32ByteStride)) {
+				EMGD_DEBUG("     ... This mode is a match!");
+				desired_mode = mode;
+				break;
+			}
+			mode++;
+		}
+		if (NULL == desired_mode) {
+			printk(KERN_ERR "No mode matching the desired width (%lu), height "
+				"(%lu), and stride (%lu) was found.",
+				dst_surf_attrib->sDims.ui32Width,
+				dst_surf_attrib->sDims.ui32Height,
+				dst_surf_attrib->sDims.ui32ByteStride);
+			return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+		} else {
+			/* Must set this in order to get the timings setup: */
+			desired_mode->flags |= IGD_DISPLAY_ENABLE;
+		}
+
+
+		/* Make the mode change by calling alter_displays(): */
+		primary_fb_info.width = desired_mode->width;
+		primary_fb_info.height = desired_mode->height;
+		primary_fb_info.pixel_format = emgd_pf;
+		primary_fb_info.flags = 0;
+		primary_fb_info.allocated = 0;
+		memcpy(&secondary_fb_info, &primary_fb_info,
+				sizeof(igd_framebuffer_info_t));
+
+		EMGD_DEBUG("Calling alter_displays()");
+		err = context->dispatch.alter_displays(context,
+			&primary, desired_mode, &primary_fb_info,
+			&secondary, desired_mode, &secondary_fb_info, priv->dc, 0);
+		if (err) {
+			printk(KERN_ERR "The alter_displays() function returned %d.", err);
+			return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+		}
+
+
+		/* Update the private copy, like emgd_alter_displays() would do: */
+		priv->primary = primary;
+		priv->secondary = secondary;
+		priv->primary_port_number = (priv->dc & 0xf0) >> 4;
+		priv->secondary_port_number = (priv->dc & 0xf00000) >> 20;
+
+
+		/* Re-initialize the display values: */
+		err = priv->reinit_3dd(drm_dev);
+		if (err != EMGD_OK) {
+			printk(KERN_ERR "The reinit_3dd() function returned %d.", err);
+			return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+		}
+	} /* end of mode-change code */
+
+	return err;
+} /* do_mode_change() */
diff --git a/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.h b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.h
new file mode 100644
index 0000000..8ea6d33
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc.h
@@ -0,0 +1,342 @@
+/**********************************************************************
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef EMGD_DC_H
+#define EMGD_DC_H
+
+#include <drm/drmP.h>
+#include "memory.h"
+#include "io.h"
+#include "emgd_shared.h"
+
+
+#define EMGDDC_MAXFORMATS 20
+#define EMGDDC_MAXDIMS 20
+
+
+#define DISPLAY_DEVICE_NAME "Intel EMGD Display Driver"
+#define	DRVNAME	"emgd_dc"
+#define	DEVNAME	DRVNAME
+#define	DRIVER_PREFIX DRVNAME
+
+
+#define	EMGD_TRACE_STUB \
+	EMGD_DEBUG("Inside the stubbed %s() function", __FUNCTION__)
+
+
+typedef struct _emgddc_devinfo  emgddc_devinfo_t;
+
+
+typedef enum tag_emgd_bool
+{
+	EMGD_FALSE = 0,
+	EMGD_TRUE  = 1,
+} emgd_bool;
+
+
+/**
+ * A pair of equivalent pixel formats, one in the EMGD format, one in the PVR
+ * format.  This structure is used to translate between the two formats.
+ */
+typedef struct _emgddc_pixelformat_translator
+{
+	/** An EMGD-formatted pixel format. */
+	unsigned long emgd_pf;
+
+	/** A PVR-formatted pixel format. */
+	PVRSRV_PIXEL_FORMAT pvr_pf;
+}  emgddc_pixelformat_translator_t;
+
+
+/** Information about a given swap chain buffer. */
+typedef struct _emgddc_buffer
+{
+	/** A copy of the drm_emgd_private associated with this buffer. */
+	drm_emgd_priv_t *priv;
+
+	/** The GMM offset of this buffer's memory. */
+	unsigned long offset;
+
+	/** This buffer's EMGD-formatted pixel format. */
+	unsigned long pixel_format;
+
+	/** This buffer's width. */
+	unsigned long width;
+
+	/** This buffer's height. */
+	unsigned long height;
+
+	/**
+	 * This buffer's stride (i.e. number of bytes between the same point on
+	 * successive scanlines).
+	 */
+	unsigned long pitch;
+
+	/** This buffer's size. */
+	unsigned long size;
+
+	/** Is this buffer the framebuffer (a.k.a. system buffer). */
+	int is_fb;
+
+	/**
+	 * The memory-mapped virtual address of the buffer (obtained from
+	 * gmm_map())
+	 */
+	IMG_CPU_VIRTADDR virt_addr;
+
+	/** The PVR sync data for this buffer */
+	PVRSRV_SYNC_DATA *sync_data;
+
+	unsigned long is_contiguous;
+
+	/**
+	 * The PVR next buffer in the swap chain (the last buffer points to the
+	 * first buffer
+	 */
+	struct _emgddc_buffer *next;
+} emgddc_buffer_t;
+
+
+/** Information for queueing a flip for a given swap chain buffer. */
+typedef struct _emgddc_flip_queue_item
+{
+	/**
+	 * A handle to a PVR services data structure that must be passed to
+	 * PVRSRVCmdComplete(), in order to "complete" a flip (i.e. when PVR
+	 * services knows that the 3DD has caused the flip to occur, and as such,
+	 * when its queue-processing code can call emgddc_process_flip() to
+	 * start/queue another flip).  "Completing" a flip does not mean that the
+	 * flip has reached the end of its swap_interval and been "cleared."
+	 */
+	IMG_HANDLE cmd_complete;
+
+	/**
+	 * The number of VBlanks after a flip occurs, before the next flip can
+	 * start.
+	 */
+	unsigned long swap_interval;
+
+	/** Whether the corresponding buffer has a flip in progress. */
+	emgd_bool valid;
+
+	/**
+	 * Whether the corresponding buffer completed a flip.  This can only be
+	 * EMGD_TRUE if valid is also EMGD_TRUE.
+	 */
+	emgd_bool flipped;
+
+	/**
+	 * Whether the corresponding buffer told PVR services that it completed a
+	 * flip.  This can only be EMGD_TRUE if flipped is also EMGD_TRUE.
+	 */
+	emgd_bool cmd_completed;
+
+	/** Which buffer is associated with this flip_item. */
+	emgddc_buffer_t *buffer;
+
+} emgddc_flip_queue_item_t;
+
+
+/** Information about a given swap chain. */
+typedef struct _emgddc_swapchain
+{
+	/**
+	 * Pointer to the parent devinfo, so that emgddc_flip() can lookup which
+	 * device (and therefore, which igd_display_t) to use.
+	 */
+	emgddc_devinfo_t *devinfo;
+
+	/** Whether this swap chain is valid for buffer flipping. */
+	emgd_bool valid;
+
+	/** Number of buffers in this swap chain. */
+	unsigned long buffer_count;
+
+	/** An array of the buffers in this swap chain. */
+	emgddc_buffer_t *buffers;
+
+	/** An array of the structures that keep track of queued flips.  Each flip
+	 * item corresponds to the identically-numbered buffer in this swap chain.
+	 */
+	emgddc_flip_queue_item_t	*flip_queue;
+
+	/** Index into both the buffers and flip_queue arrays.  Used when queueing
+	 * (or inserting) flips.  Is incremented until it gets too large, and then
+	 * is zero'd-out.
+	 */
+	unsigned long insert_index;
+
+	/** Index into both the buffers and flip_queue arrays.  Used when flushing
+	 * (or removing from) the flip queue.  Is incremented until it gets too
+	 * large, and then is zero'd-out.
+	 */
+	unsigned long remove_index;
+
+#ifdef SUPPORT_FB_EVENTS
+	emgd_bool blanked;
+#endif /* SUPPORT_FB_EVENTS */
+
+	/** Type of swap chain */
+	unsigned long flags;
+
+	/** A copy of emgddc_devinfo_t.pvr_jtable. */
+	PVRSRV_DC_DISP2SRV_KMJTABLE	*pvr_jtable;
+
+	/** Next swap chain in the list */
+	struct _emgddc_swapchain *next;
+} emgddc_swapchain_t;
+
+
+/** Information about the device. */
+struct _emgddc_devinfo
+{
+	/*
+	 * The following values are display-dependent, and are dynamically
+	 * re-initialized after an EMGD alter_displays() call:
+	 */
+
+	/** The size (in bytes) of the framebuffer and future swap chain buffers. */
+	unsigned long fb_size;
+
+	/** The width (in pixels) of the framebuffer. */
+	unsigned long width;
+
+	/** The height (in pixels) of the framebuffer. */
+	unsigned long height;
+
+	/** The stride (in bytes) from one row of the framebuffer to another. */
+	unsigned long byte_stride;
+
+	/* The number of dimensions for the primary display: */
+	unsigned long num_dims;
+
+	/* The supported dimensions for the primary display: */
+	DISPLAY_DIMS display_dim_list[EMGDDC_MAXDIMS];
+
+	/** The one EMGD-formatted pixel format (before translation) being used. */
+	unsigned long emgd_pf;
+
+	/** The one PVR-formatted pixel format (after translation) being used. */
+	PVRSRV_PIXEL_FORMAT pvr_pf;
+
+	/** The number of pixel formats for the primary display. */
+	unsigned long num_formats;
+
+	/** The supported PVR pixel formats for the primary display. */
+	DISPLAY_FORMAT display_format_list[EMGDDC_MAXFORMATS];
+
+	/** The frame buffer (a.k.a. "system buffer" or "front buffer"). */
+	emgddc_buffer_t system_buffer;
+
+
+	/*
+	 * The following values are display-independent, are statically
+	 * initialized at start-up time, and some may be altered during run time:
+	 */
+
+	/** 0 for the primary devinfo, 1 for the secondary/DIH mode devinfo */
+	int which_devinfo;
+
+	/** A copy of the drm_emgd_private associated with this devinfo. */
+	drm_emgd_priv_t *priv;
+
+	/** Private copy of the drm_device associated with this devinfo. */
+	struct drm_device *drm_device;
+
+	/**
+	 * The first of potentially multiple swap chains that support full-screen
+	 * buffer flipping.
+	 */
+	emgddc_swapchain_t *flipable_swapchains;
+
+	/** The first of potentially many swap chains that support pixmaps. */
+	emgddc_swapchain_t *pixmap_swapchains;
+
+	/** Counter to provide unique IDs to each swap chain. */
+	unsigned long swap_chain_id_counter;
+
+	/** Static information about swap chains, plus the driver's string name. */
+	DISPLAY_INFO display_info;
+
+	/** HAL handle associated with this devinfo for dealing with interrupts. */
+	emgd_vblank_callback_h interrupt_h;
+
+	/** Handle very rare case of not being able to [re-]enable interrupts. */
+	emgd_bool flipping_disabled;
+
+	/** If EMGD_TRUE, don't queue buffer flips, but flip/complete right away. */
+	emgd_bool flush_commands;
+
+	/**
+	 * A counter so that the state of flush_commands must be set to EMGD_TRUE
+	 * and EMGD_FALSE an equal number of times before the state actually
+	 * changes.
+	 */
+	unsigned long set_flush_state_ref_count;
+
+	/**
+	 * A spinlock to prevent contention between regular code and
+	 * interrupt-handling code.
+	 */
+	spinlock_t swap_chain_lock;
+
+#ifdef SUPPORT_FB_EVENTS
+	struct notifier_block lin_notif_block;
+#endif /* SUPPORT_FB_EVENTS */
+
+	/** PVR services functions. */
+	PVRSRV_DC_DISP2SRV_KMJTABLE	pvr_jtable;
+
+	/** Functions we provide to PVR services. */
+	PVRSRV_DC_SRV2DISP_KMJTABLE	dc_jtable;
+
+	/** This device's numeric ID, obtained when registering with PVR services */
+	unsigned long device_id;
+
+};
+
+
+typedef enum _emgd_error
+{
+	EMGD_OK                             =  0,
+	EMGD_ERROR_GENERIC                  =  1,
+	EMGD_ERROR_OUT_OF_MEMORY            =  2,
+	EMGD_ERROR_TOO_FEW_BUFFERS          =  3,
+	EMGD_ERROR_INVALID_PARAMS           =  4,
+	EMGD_ERROR_INIT_FAILURE             =  5,
+	EMGD_ERROR_CANT_REGISTER_CALLBACK   =  6,
+	EMGD_ERROR_INVALID_DEVICE           =  7,
+	EMGD_ERROR_DEVICE_REGISTER_FAILED   =  8
+} emgd_error_t;
+
+
+#ifndef UNREFERENCED_PARAMETER
+#define	UNREFERENCED_PARAMETER(param) (param) = (param)
+#endif
+
+
+emgd_error_t emgddc_init(struct drm_device * dev);
+emgd_error_t emgddc_deinit(void);
+
+void emgddc_flip(emgddc_swapchain_t *swap_chain, emgddc_buffer_t *buffer);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc_linux.c b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc_linux.c
new file mode 100644
index 0000000..c8d8cdf
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/3rdparty/emgd_displayclass/emgd_dc_linux.c
@@ -0,0 +1,153 @@
+/**********************************************************************
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ ******************************************************************************/
+#define MODULE_NAME hal.pvr3dd
+
+#include "drm_emgd_private.h"
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kerneldisplay.h"
+#include "emgd_dc.h"
+
+
+#if !defined(SUPPORT_DRI_DRM)
+#error "SUPPORT_DRI_DRM must be set"
+#endif
+
+
+/* The following macros exist to help the PVR services code name/find and call
+ * the Init and Cleanup functions below.  The DISPLAY_CONTROLLER macro must be
+ * set in the build, so that the PVR service code can use the same magic to
+ * discover the name of the Init and Cleanup functions for this driver.
+ */
+#if !defined(DISPLAY_CONTROLLER)
+#define DISPLAY_CONTROLLER emgd_dc
+#endif
+#define MAKENAME_HELPER(x, y) x ## y
+#define	MAKENAME2(x, y) MAKENAME_HELPER(x, y)
+#define	MAKENAME(x) MAKENAME2(DISPLAY_CONTROLLER, x)
+
+
+/* The following tells GCC to not warn about ununsed functions: */
+#define unref__ __attribute__ ((unused))
+
+
+/**
+ * Function that initializes and starts this 3rd-party display driver.  This is
+ * called by the PVR services when it starts.
+ *
+ * @param dev (IN) The drm_device associated with this driver.
+ */
+int MAKENAME(_Init)(struct drm_device unref__ *dev)
+{
+	EMGD_TRACE_ENTER;
+
+	if (emgddc_init(dev) != EMGD_OK) {
+		EMGD_ERROR_EXIT(DRVNAME " init failed (" DISPLAY_DEVICE_NAME ")\n");
+		return -ENODEV;
+	}
+
+	EMGD_TRACE_EXIT;
+	return 0;
+}
+
+
+/**
+ * Function that shuts-down and de-initializes this 3rd-party display driver.
+ * This is called by the PVR services when it ends.
+ *
+ * @param dev (IN) The drm_device associated with this driver.
+ */
+void MAKENAME(_Cleanup)(struct drm_device unref__ *dev)
+{
+	EMGD_TRACE_ENTER;
+
+	if (emgddc_deinit() != EMGD_OK) {
+		EMGD_ERROR_EXIT(DRVNAME " de-init failed (" DISPLAY_DEVICE_NAME ")\n");
+	}
+
+	EMGD_TRACE_EXIT;
+}
+
+
+/**
+ * Set the display to the surface specified by buffer.
+ *
+ * @param swap_chain (IN) Pointer to the swap chain associated with buffer.
+ * @param buffer (IN) Pointer to the buffer to display.
+ */
+void emgddc_flip(emgddc_swapchain_t *swap_chain, emgddc_buffer_t *buffer)
+{
+	drm_emgd_priv_t *priv = buffer->priv;
+	igd_context_t *context = priv->context;
+	igd_surface_t surf;
+	int ret;
+
+	EMGD_TRACE_ENTER;
+	EMGD_DEBUG("Parameters: swap_chain=0x%p", swap_chain);
+	EMGD_DEBUG("  buffer=0x%p, *buffer->offset=0x%08lx",
+		buffer, buffer->offset);
+
+	if (EMGD_FALSE == swap_chain->valid) {
+		EMGD_DEBUG("Not flipping--swap chain invalidated by a mode change.");
+		EMGD_TRACE_EXIT;
+		return;
+	}
+
+	surf.offset = buffer->offset;
+	surf.pitch = buffer->pitch;
+	surf.width = buffer->width;
+	surf.height = buffer->height;
+	surf.pixel_format = buffer->pixel_format;
+	surf.flags = IGD_SURFACE_RENDER | IGD_SURFACE_DISPLAY;
+
+	/* Flip the primary surface.  Select a different EMGD display depending on
+	 * the DC & devinfo:
+	 */
+	if (IGD_DC_EXTENDED(priv->dc) &&
+		(swap_chain->devinfo->which_devinfo == 1))  {
+		ret = context->dispatch.set_surface(priv->secondary,
+			IGD_PRIORITY_NORMAL, IGD_BUFFER_DISPLAY, &surf, NULL, 0);
+		if (ret != 0) {
+			printk(KERN_ERR "%s: set_surface() returned %d", __FUNCTION__, ret);
+		}
+	} else {
+		ret = context->dispatch.set_surface(priv->primary,
+			IGD_PRIORITY_NORMAL, IGD_BUFFER_DISPLAY, &surf, NULL, 0);
+		if (ret != 0) {
+			printk(KERN_ERR "%s: set_surface() returned %d", __FUNCTION__, ret);
+		}
+	}
+
+	/* Flip the secondary surface: */
+	if (IGD_DC_CLONE(priv->dc)) {
+		/* If in clone mode, flip the other pipe too: */
+		ret = context->dispatch.set_surface(priv->secondary,
+			IGD_PRIORITY_NORMAL, IGD_BUFFER_DISPLAY, &surf, NULL, 0);
+		if (ret != 0) {
+			printk(KERN_ERR "%s: set_surface() returned %d", __FUNCTION__, ret);
+		}
+	}
+
+
+	EMGD_TRACE_EXIT;
+} /* emgddc_flip() */
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/env/linux/pvr_drm_shared.h b/drivers/gpu/drm/emgd/pvr/services4/include/env/linux/pvr_drm_shared.h
new file mode 100644
index 0000000..7f0f445
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/env/linux/pvr_drm_shared.h
@@ -0,0 +1,59 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__PVR_DRM_SHARED_H__)
+#define __PVR_DRM_SHARED_H__
+
+#if defined(SUPPORT_DRI_DRM)
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+#define PVR_DRM_SRVKM_CMD	DRM_PVR_RESERVED1
+#define	PVR_DRM_DISP_CMD	DRM_PVR_RESERVED2
+#define	PVR_DRM_BC_CMD		DRM_PVR_RESERVED3
+#define PVR_DRM_IS_MASTER_CMD	DRM_PVR_RESERVED4
+#define PVR_DRM_UNPRIV_CMD	DRM_PVR_RESERVED5
+#define PVR_DRM_DBGDRV_CMD	DRM_PVR_RESERVED6
+#else
+#define PVR_DRM_SRVKM_CMD	0
+#define	PVR_DRM_DISP_CMD	1
+#define	PVR_DRM_BC_CMD		2
+#define PVR_DRM_IS_MASTER_CMD	3
+#define PVR_DRM_UNPRIV_CMD	4
+#define PVR_DRM_DBGDRV_CMD	5
+#endif
+
+#define	PVR_DRM_UNPRIV_INIT_SUCCESFUL	0
+#define	PVR_DRM_UNPRIV_BUSID_TYPE	1
+#define	PVR_DRM_UNPRIV_BUSID_FIELD	2
+
+#define	PVR_DRM_BUS_TYPE_PCI		0
+
+#define	PVR_DRM_PCI_DOMAIN		0
+#define	PVR_DRM_PCI_BUS			1
+#define	PVR_DRM_PCI_DEV			2
+#define	PVR_DRM_PCI_FUNC		3
+
+#endif
+
+#endif
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/kernelbuffer.h b/drivers/gpu/drm/emgd/pvr/services4/include/kernelbuffer.h
new file mode 100644
index 0000000..4bf59b1
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/kernelbuffer.h
@@ -0,0 +1,57 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__KERNELBUFFER_H__)
+#define __KERNELBUFFER_H__
+
+typedef PVRSRV_ERROR (*PFN_OPEN_BC_DEVICE)(IMG_UINT32, IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_CLOSE_BC_DEVICE)(IMG_UINT32, IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_GET_BC_INFO)(IMG_HANDLE, BUFFER_INFO*);
+typedef PVRSRV_ERROR (*PFN_GET_BC_BUFFER)(IMG_HANDLE, IMG_UINT32, PVRSRV_SYNC_DATA*, IMG_HANDLE*);
+
+typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG
+{
+	IMG_UINT32							ui32TableSize;
+	PFN_OPEN_BC_DEVICE					pfnOpenBCDevice;
+	PFN_CLOSE_BC_DEVICE					pfnCloseBCDevice;
+	PFN_GET_BC_INFO						pfnGetBCInfo;
+	PFN_GET_BC_BUFFER					pfnGetBCBuffer;
+	PFN_GET_BUFFER_ADDR					pfnGetBufferAddr;
+	PFN_GET_BUFFER_ID_FROM_TAG			pfnGetBufferIdFromTag;
+
+} PVRSRV_BC_SRV2BUFFER_KMJTABLE;
+
+
+typedef PVRSRV_ERROR (*PFN_BC_REGISTER_BUFFER_DEV)(PVRSRV_BC_SRV2BUFFER_KMJTABLE*, IMG_UINT32*);
+typedef PVRSRV_ERROR (*PFN_BC_REMOVE_BUFFER_DEV)(IMG_UINT32);
+
+typedef struct PVRSRV_BC_BUFFER2SRV_KMJTABLE_TAG
+{
+	IMG_UINT32							ui32TableSize;
+	PFN_BC_REGISTER_BUFFER_DEV			pfnPVRSRVRegisterBCDevice;
+	PFN_BC_REMOVE_BUFFER_DEV			pfnPVRSRVRemoveBCDevice;
+
+} PVRSRV_BC_BUFFER2SRV_KMJTABLE, *PPVRSRV_BC_BUFFER2SRV_KMJTABLE;
+
+typedef IMG_BOOL (*PFN_BC_GET_PVRJTABLE) (PPVRSRV_BC_BUFFER2SRV_KMJTABLE);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/kerneldisplay.h b/drivers/gpu/drm/emgd/pvr/services4/include/kerneldisplay.h
new file mode 100644
index 0000000..b14c131
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/kerneldisplay.h
@@ -0,0 +1,152 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__KERNELDISPLAY_H__)
+#define __KERNELDISPLAY_H__
+
+typedef PVRSRV_ERROR (*PFN_OPEN_DC_DEVICE)(IMG_UINT32, IMG_HANDLE*, PVRSRV_SYNC_DATA*);
+typedef PVRSRV_ERROR (*PFN_CLOSE_DC_DEVICE)(IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_ENUM_DC_FORMATS)(IMG_HANDLE, IMG_UINT32*, DISPLAY_FORMAT*);
+typedef PVRSRV_ERROR (*PFN_ENUM_DC_DIMS)(IMG_HANDLE,
+										 DISPLAY_FORMAT*,
+										 IMG_UINT32*,
+										 DISPLAY_DIMS*);
+typedef PVRSRV_ERROR (*PFN_GET_DC_SYSTEMBUFFER)(IMG_HANDLE, IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_GET_DC_INFO)(IMG_HANDLE, DISPLAY_INFO*);
+typedef PVRSRV_ERROR (*PFN_CREATE_DC_SWAPCHAIN)(IMG_HANDLE,
+												IMG_UINT32,
+												DISPLAY_SURF_ATTRIBUTES*,
+												DISPLAY_SURF_ATTRIBUTES*,
+												IMG_UINT32,
+												PVRSRV_SYNC_DATA**,
+												IMG_UINT32,
+												IMG_HANDLE*,
+												IMG_UINT32*);
+typedef PVRSRV_ERROR (*PFN_DESTROY_DC_SWAPCHAIN)(IMG_HANDLE,
+												 IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_SET_DC_DSTRECT)(IMG_HANDLE, IMG_HANDLE, IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SET_DC_SRCRECT)(IMG_HANDLE, IMG_HANDLE, IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SET_DC_DSTCK)(IMG_HANDLE, IMG_HANDLE, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_SET_DC_SRCCK)(IMG_HANDLE, IMG_HANDLE, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_GET_DC_BUFFERS)(IMG_HANDLE,
+										   IMG_HANDLE,
+										   IMG_UINT32*,
+										   IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_SWAP_TO_DC_BUFFER)(IMG_HANDLE,
+											  IMG_HANDLE,
+											  IMG_UINT32,
+											  IMG_HANDLE,
+											  IMG_UINT32,
+											  IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SWAP_TO_DC_SYSTEM)(IMG_HANDLE, IMG_HANDLE);
+typedef IMG_VOID (*PFN_QUERY_SWAP_COMMAND_ID)(IMG_HANDLE, IMG_HANDLE, IMG_HANDLE, IMG_HANDLE, IMG_UINT16*, IMG_BOOL*);
+typedef IMG_VOID (*PFN_SET_DC_STATE)(IMG_HANDLE, IMG_UINT32);
+
+typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG
+{
+	IMG_UINT32						ui32TableSize;
+	PFN_OPEN_DC_DEVICE				pfnOpenDCDevice;
+	PFN_CLOSE_DC_DEVICE				pfnCloseDCDevice;
+	PFN_ENUM_DC_FORMATS				pfnEnumDCFormats;
+	PFN_ENUM_DC_DIMS				pfnEnumDCDims;
+	PFN_GET_DC_SYSTEMBUFFER			pfnGetDCSystemBuffer;
+	PFN_GET_DC_INFO					pfnGetDCInfo;
+	PFN_GET_BUFFER_ADDR				pfnGetBufferAddr;
+	PFN_CREATE_DC_SWAPCHAIN			pfnCreateDCSwapChain;
+	PFN_DESTROY_DC_SWAPCHAIN		pfnDestroyDCSwapChain;
+	PFN_SET_DC_DSTRECT				pfnSetDCDstRect;
+	PFN_SET_DC_SRCRECT				pfnSetDCSrcRect;
+	PFN_SET_DC_DSTCK				pfnSetDCDstColourKey;
+	PFN_SET_DC_SRCCK				pfnSetDCSrcColourKey;
+	PFN_GET_DC_BUFFERS				pfnGetDCBuffers;
+	PFN_SWAP_TO_DC_BUFFER			pfnSwapToDCBuffer;
+	PFN_SWAP_TO_DC_SYSTEM			pfnSwapToDCSystem;
+	PFN_SET_DC_STATE				pfnSetDCState;
+	PFN_QUERY_SWAP_COMMAND_ID		pfnQuerySwapCommandID;
+
+} PVRSRV_DC_SRV2DISP_KMJTABLE;
+
+typedef IMG_BOOL (*PFN_ISR_HANDLER)(IMG_VOID*);
+
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_DISPLAY_DEV)(PVRSRV_DC_SRV2DISP_KMJTABLE*, IMG_UINT32*);
+typedef PVRSRV_ERROR (*PFN_DC_REMOVE_DISPLAY_DEV)(IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_OEM_FUNCTION)(IMG_UINT32, IMG_VOID*, IMG_UINT32, IMG_VOID*, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_COMMANDPROCLIST)(IMG_UINT32, PPFN_CMD_PROC,IMG_UINT32[][2], IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REMOVE_COMMANDPROCLIST)(IMG_UINT32, IMG_UINT32);
+typedef IMG_VOID (*PFN_DC_CMD_COMPLETE)(IMG_HANDLE, IMG_BOOL);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_SYS_ISR)(PFN_ISR_HANDLER, IMG_VOID*, IMG_UINT32, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_POWER)(IMG_UINT32, PFN_PRE_POWER, PFN_POST_POWER,
+											  PFN_PRE_CLOCKSPEED_CHANGE, PFN_POST_CLOCKSPEED_CHANGE,
+											  IMG_HANDLE, PVRSRV_DEV_POWER_STATE, PVRSRV_DEV_POWER_STATE);
+
+typedef struct PVRSRV_DC_DISP2SRV_KMJTABLE_TAG
+{
+	IMG_UINT32						ui32TableSize;
+	PFN_DC_REGISTER_DISPLAY_DEV		pfnPVRSRVRegisterDCDevice;
+	PFN_DC_REMOVE_DISPLAY_DEV		pfnPVRSRVRemoveDCDevice;
+	PFN_DC_OEM_FUNCTION				pfnPVRSRVOEMFunction;
+	PFN_DC_REGISTER_COMMANDPROCLIST	pfnPVRSRVRegisterCmdProcList;
+	PFN_DC_REMOVE_COMMANDPROCLIST	pfnPVRSRVRemoveCmdProcList;
+	PFN_DC_CMD_COMPLETE				pfnPVRSRVCmdComplete;
+	PFN_DC_REGISTER_SYS_ISR			pfnPVRSRVRegisterSystemISRHandler;
+	PFN_DC_REGISTER_POWER			pfnPVRSRVRegisterPowerDevice;
+	PFN_DC_CMD_COMPLETE				pfnPVRSRVFreeCmdCompletePacket;
+} PVRSRV_DC_DISP2SRV_KMJTABLE, *PPVRSRV_DC_DISP2SRV_KMJTABLE;
+
+
+typedef struct DISPLAYCLASS_FLIP_COMMAND_TAG
+{
+
+	IMG_HANDLE hExtDevice;
+
+
+	IMG_HANDLE hExtSwapChain;
+
+
+	IMG_HANDLE hExtBuffer;
+
+
+	IMG_HANDLE hPrivateTag;
+
+
+	IMG_UINT32 ui32ClipRectCount;
+
+
+	IMG_RECT *psClipRect;
+
+
+	IMG_UINT32	ui32SwapInterval;
+
+} DISPLAYCLASS_FLIP_COMMAND;
+
+#define DC_FLIP_COMMAND		0
+
+#define DC_STATE_NO_FLUSH_COMMANDS		0
+#define DC_STATE_FLUSH_COMMANDS			1
+
+
+typedef IMG_BOOL (*PFN_DC_GET_PVRJTABLE)(PPVRSRV_DC_DISP2SRV_KMJTABLE);
+
+
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/pvr_bridge.h b/drivers/gpu/drm/emgd/pvr/services4/include/pvr_bridge.h
new file mode 100644
index 0000000..9e6004ee
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/pvr_bridge.h
@@ -0,0 +1,1380 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __PVR_BRIDGE_H__
+#define __PVR_BRIDGE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "servicesint.h"
+
+#ifdef __linux__
+
+		#include <linux/ioctl.h>
+
+    #define PVRSRV_IOC_GID      'g'
+    #define PVRSRV_IO(INDEX)    _IO(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+    #define PVRSRV_IOW(INDEX)   _IOW(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+    #define PVRSRV_IOR(INDEX)   _IOR(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+    #define PVRSRV_IOWR(INDEX)  _IOWR(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+
+#else
+
+			#error Unknown platform: Cannot define ioctls
+
+	#define PVRSRV_IO(INDEX)    (PVRSRV_IOC_GID + INDEX)
+	#define PVRSRV_IOW(INDEX)   (PVRSRV_IOC_GID + INDEX)
+	#define PVRSRV_IOR(INDEX)   (PVRSRV_IOC_GID + INDEX)
+	#define PVRSRV_IOWR(INDEX)  (PVRSRV_IOC_GID + INDEX)
+
+	#define PVRSRV_BRIDGE_BASE                  PVRSRV_IOC_GID
+#endif
+
+
+#define PVRSRV_BRIDGE_CORE_CMD_FIRST			0UL
+#define PVRSRV_BRIDGE_ENUM_DEVICES				PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_RELEASE_DEVICEINFO		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_ALLOC_DEVICEMEM			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_FREE_DEVICEMEM			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_GETFREE_DEVICEMEM			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_CREATE_COMMANDQUEUE		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_DESTROY_COMMANDQUEUE		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+10)
+#define	PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA           PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_CONNECT_SERVICES			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_DISCONNECT_SERVICES		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_WRAP_DEVICE_MEM			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_GET_DEVICEMEMINFO			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_RESERVE_DEV_VIRTMEM		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_FREE_DEV_VIRTMEM			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_MAP_EXT_MEMORY			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_UNMAP_EXT_MEMORY			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+19)
+#define PVRSRV_BRIDGE_MAP_DEV_MEMORY			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+20)
+#define PVRSRV_BRIDGE_UNMAP_DEV_MEMORY			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+21)
+#define PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY	PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+22)
+#define PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY	PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+23)
+#define PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+24)
+#define PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER	PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+25)
+#define PVRSRV_BRIDGE_EXPORT_DEVICEMEM			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+26)
+#define PVRSRV_BRIDGE_RELEASE_MMAP_DATA			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+27)
+#define PVRSRV_BRIDGE_CORE_CMD_LAST				(PVRSRV_BRIDGE_CORE_CMD_FIRST+27)
+
+#define PVRSRV_BRIDGE_SIM_CMD_FIRST				(PVRSRV_BRIDGE_CORE_CMD_LAST+1)
+#define PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT		PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_REGISTER_SIM_PROCESS		PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS	PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_SIM_CMD_LAST				(PVRSRV_BRIDGE_SIM_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_MAPPING_CMD_FIRST			(PVRSRV_BRIDGE_SIM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_MAPPHYSTOUSERSPACE		PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE		PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP		PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_MAPPING_CMD_LAST			(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_STATS_CMD_FIRST			(PVRSRV_BRIDGE_MAPPING_CMD_LAST+1)
+#define	PVRSRV_BRIDGE_GET_FB_STATS				PVRSRV_IOWR(PVRSRV_BRIDGE_STATS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_STATS_CMD_LAST			(PVRSRV_BRIDGE_STATS_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_MISC_CMD_FIRST			(PVRSRV_BRIDGE_STATS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_MISC_INFO				PVRSRV_IOWR(PVRSRV_BRIDGE_MISC_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_RELEASE_MISC_INFO			PVRSRV_IOWR(PVRSRV_BRIDGE_MISC_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MISC_CMD_LAST				(PVRSRV_BRIDGE_MISC_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_OVERLAY_CMD_FIRST			(PVRSRV_BRIDGE_MISC_CMD_LAST+1)
+#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
+#define PVRSRV_BRIDGE_INIT_3D_OVL_BLT_RES		PVRSRV_IOWR(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DEINIT_3D_OVL_BLT_RES		PVRSRV_IOWR(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
+#endif
+#define PVRSRV_BRIDGE_OVERLAY_CMD_LAST			(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
+
+#if defined(PDUMP)
+#define PVRSRV_BRIDGE_PDUMP_CMD_FIRST			(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_PDUMP_INIT			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_PDUMP_MEMPOL			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_PDUMP_DUMPMEM			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_PDUMP_REG				PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_PDUMP_REGPOL			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_PDUMP_COMMENT			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_PDUMP_SETFRAME			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_PDUMP_ISCAPTURING			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_PDUMP_DUMPBITMAP			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_PDUMP_DUMPREADREG			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_PDUMP_SYNCPOL			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_PDUMP_DUMPSYNC			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_PDUMP_MEMPAGES			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_PDUMP_DRIVERINFO			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_PDUMP_PDREG			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR		PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ	PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_PDUMP_STARTINITPHASE			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_PDUMP_STOPINITPHASE			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST			(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
+#else
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST			PVRSRV_BRIDGE_OVERLAY_CMD_LAST
+#endif
+
+#define PVRSRV_BRIDGE_OEM_CMD_FIRST				(PVRSRV_BRIDGE_PDUMP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_OEMJTABLE				PVRSRV_IOWR(PVRSRV_BRIDGE_OEM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_OEM_CMD_LAST				(PVRSRV_BRIDGE_OEM_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST		(PVRSRV_BRIDGE_OEM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_ENUM_CLASS				PVRSRV_IOWR(PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DEVCLASS_CMD_LAST			(PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST		(PVRSRV_BRIDGE_DEVCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE	PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS	PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER	PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_INFO		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER	PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM	PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_DISPCLASS_CMD_LAST		(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+14)
+
+
+#define PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST		(PVRSRV_BRIDGE_DISPCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE	PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE	PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO		PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER	PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER_ID_FROM_TAG PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_BUFCLASS_CMD_LAST			(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+4)
+
+#define PVRSRV_BRIDGE_WRAP_CMD_FIRST			(PVRSRV_BRIDGE_BUFCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_WRAP_EXT_MEMORY			PVRSRV_IOWR(PVRSRV_BRIDGE_WRAP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY			PVRSRV_IOWR(PVRSRV_BRIDGE_WRAP_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_WRAP_CMD_LAST				(PVRSRV_BRIDGE_WRAP_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST		(PVRSRV_BRIDGE_WRAP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM		PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM		PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MAP_MEMINFO_MEM			PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_UNMAP_MEMINFO_MEM			PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_SHAREDMEM_CMD_LAST		(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+3)
+
+#define PVRSRV_BRIDGE_SERVICES4_TMP_CMD_FIRST	(PVRSRV_BRIDGE_SHAREDMEM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GETMMU_PD_DEVPADDR        PVRSRV_IOWR(PVRSRV_BRIDGE_SERVICES4_TMP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_SERVICES4_TMP_CMD_LAST	(PVRSRV_BRIDGE_SERVICES4_TMP_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_INITSRV_CMD_FIRST			(PVRSRV_BRIDGE_SERVICES4_TMP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_INITSRV_CONNECT			PVRSRV_IOWR(PVRSRV_BRIDGE_INITSRV_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_INITSRV_DISCONNECT		PVRSRV_IOWR(PVRSRV_BRIDGE_INITSRV_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_INITSRV_CMD_LAST			(PVRSRV_BRIDGE_INITSRV_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST	(PVRSRV_BRIDGE_INITSRV_CMD_LAST+1)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_WAIT			PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_OPEN			PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE		PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CMD_LAST		(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST		(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_LAST+1)
+#define PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS	PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS	PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_SYNC_OPS_CMD_LAST			(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD		(PVRSRV_BRIDGE_SYNC_OPS_CMD_LAST+1)
+
+
+#define PVRSRV_KERNEL_MODE_CLIENT				1
+
+typedef struct PVRSRV_BRIDGE_RETURN_TAG
+{
+	PVRSRV_ERROR eError;
+	IMG_VOID *pvData;
+
+}PVRSRV_BRIDGE_RETURN;
+
+
+typedef struct PVRSRV_BRIDGE_PACKAGE_TAG
+{
+	IMG_UINT32				ui32BridgeID;
+	IMG_UINT32				ui32Size;
+	IMG_VOID				*pvParamIn;
+	IMG_UINT32				ui32InBufferSize;
+	IMG_VOID				*pvParamOut;
+	IMG_UINT32				ui32OutBufferSize;
+
+	IMG_HANDLE				hKernelServices;
+}PVRSRV_BRIDGE_PACKAGE;
+
+
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_UINT32			uiDevIndex;
+	PVRSRV_DEVICE_TYPE	eDeviceType;
+
+} PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ENUMCLASS_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	PVRSRV_DEVICE_CLASS sDeviceClass;
+} PVRSRV_BRIDGE_IN_ENUMCLASS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDeviceKM;
+} PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDeviceKM;
+} PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDeviceKM;
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDeviceKM;
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDeviceKM;
+} PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDeviceKM;
+} PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_DEVICEINFO_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDevCookie;
+
+} PVRSRV_BRIDGE_IN_RELEASE_DEVICEINFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_CLASSDEVICEINFO_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	PVRSRV_DEVICE_CLASS DeviceClass;
+	IMG_VOID*			pvDevInfo;
+
+}PVRSRV_BRIDGE_IN_FREE_CLASSDEVICEINFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDevCookie;
+	IMG_HANDLE 			hDevMemContext;
+
+}PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDevCookie;
+
+}PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE 			hDevCookie;
+	IMG_HANDLE 			hDevMemContext;
+
+}PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDevCookie;
+	IMG_HANDLE			hDevMemHeap;
+	IMG_UINT32			ui32Attribs;
+	IMG_SIZE_T			ui32Size;
+	IMG_SIZE_T			ui32Alignment;
+
+}PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAPMEMINFOTOUSER_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	PVRSRV_KERNEL_MEM_INFO	*psKernelMemInfo;
+
+}PVRSRV_BRIDGE_IN_MAPMEMINFOTOUSER;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAPMEMINFOFROMUSER_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	PVRSRV_KERNEL_MEM_INFO	*psKernelMemInfo;
+	IMG_PVOID				 pvLinAddr;
+	IMG_HANDLE				 hMappingInfo;
+
+}PVRSRV_BRIDGE_IN_UNMAPMEMINFOFROMUSER;
+
+
+typedef struct PVRSRV_BRIDGE_IN_FREEDEVICEMEM_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	IMG_HANDLE				hDevCookie;
+	PVRSRV_KERNEL_MEM_INFO	*psKernelMemInfo;
+	PVRSRV_CLIENT_MEM_INFO	sClientMemInfo;
+
+}PVRSRV_BRIDGE_IN_FREEDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	IMG_HANDLE				hDevCookie;
+	PVRSRV_KERNEL_MEM_INFO	*psKernelMemInfo;
+
+}PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_UINT32			ui32Flags;
+
+} PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CREATECOMMANDQUEUE_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDevCookie;
+	IMG_SIZE_T			ui32QueueSize;
+
+}PVRSRV_BRIDGE_IN_CREATECOMMANDQUEUE;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROYCOMMANDQUEUE_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDevCookie;
+	PVRSRV_QUEUE_INFO	*psQueueInfo;
+
+}PVRSRV_BRIDGE_IN_DESTROYCOMMANDQUEUE;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hMHandle;
+} PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hMHandle;
+} PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_RESERVE_DEV_VIRTMEM_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDevMemHeap;
+	IMG_DEV_VIRTADDR	*psDevVAddr;
+	IMG_SIZE_T			ui32Size;
+	IMG_SIZE_T			ui32Alignment;
+
+}PVRSRV_BRIDGE_IN_RESERVE_DEV_VIRTMEM;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CONNECT_SERVICES_TAG
+{
+	PVRSRV_ERROR 			eError;
+	IMG_HANDLE		hKernelServices;
+}PVRSRV_BRIDGE_OUT_CONNECT_SERVICES;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_RESERVE_DEV_VIRTMEM_TAG
+{
+	PVRSRV_ERROR 			eError;
+	PVRSRV_KERNEL_MEM_INFO	*psKernelMemInfo;
+	PVRSRV_KERNEL_SYNC_INFO	*psKernelSyncInfo;
+	PVRSRV_CLIENT_MEM_INFO	sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO	sClientSyncInfo;
+
+}PVRSRV_BRIDGE_OUT_RESERVE_DEV_VIRTMEM;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_DEV_VIRTMEM_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	PVRSRV_KERNEL_MEM_INFO	*psKernelMemInfo;
+	PVRSRV_CLIENT_MEM_INFO	sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO	sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_FREE_DEV_VIRTMEM;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	IMG_HANDLE				hKernelMemInfo;
+	IMG_HANDLE				hDstDevMemHeap;
+
+}PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY_TAG
+{
+	PVRSRV_ERROR			eError;
+	PVRSRV_KERNEL_MEM_INFO	*psDstKernelMemInfo;
+	PVRSRV_KERNEL_SYNC_INFO	*psDstKernelSyncInfo;
+	PVRSRV_CLIENT_MEM_INFO	sDstClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO	sDstClientSyncInfo;
+
+}PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY_TAG
+{
+	IMG_UINT32					ui32BridgeFlags;
+	PVRSRV_KERNEL_MEM_INFO		*psKernelMemInfo;
+	PVRSRV_CLIENT_MEM_INFO		sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO		sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_EXT_MEMORY_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	PVRSRV_KERNEL_MEM_INFO	*psKernelMemInfo;
+	IMG_SYS_PHYADDR			*psSysPAddr;
+	IMG_UINT32				ui32Flags;
+
+}PVRSRV_BRIDGE_IN_MAP_EXT_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_EXT_MEMORY_TAG
+{
+	IMG_UINT32					ui32BridgeFlags;
+	PVRSRV_CLIENT_MEM_INFO		sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO		sClientSyncInfo;
+	IMG_UINT32					ui32Flags;
+
+}PVRSRV_BRIDGE_IN_UNMAP_EXT_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY_TAG
+{
+	IMG_UINT32					ui32BridgeFlags;
+	IMG_HANDLE		hDeviceClassBuffer;
+	IMG_HANDLE		hDevMemContext;
+
+}PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY_TAG
+{
+	PVRSRV_ERROR			eError;
+	PVRSRV_CLIENT_MEM_INFO	sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+	PVRSRV_KERNEL_MEM_INFO	*psKernelMemInfo;
+	PVRSRV_KERNEL_SYNC_INFO	*psKernelSyncInfo;
+	IMG_HANDLE				hMappingInfo;
+
+}PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	PVRSRV_KERNEL_MEM_INFO	*psKernelMemInfo;
+	PVRSRV_CLIENT_MEM_INFO	sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO	sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_MEMPOL_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	PVRSRV_KERNEL_MEM_INFO	*psKernelMemInfo;
+	IMG_UINT32 ui32Offset;
+	IMG_UINT32 ui32Value;
+	IMG_UINT32 ui32Mask;
+	IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_MEMPOL;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	PVRSRV_KERNEL_SYNC_INFO	*psKernelSyncInfo;
+	IMG_BOOL bIsRead;
+	IMG_UINT32 ui32Value;
+	IMG_UINT32 ui32Mask;
+
+}PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_PVOID pvLinAddr;
+	IMG_PVOID pvAltLinAddr;
+	PVRSRV_KERNEL_MEM_INFO	*psKernelMemInfo;
+	IMG_UINT32 ui32Offset;
+	IMG_UINT32 ui32Bytes;
+	IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_PVOID pvAltLinAddr;
+	PVRSRV_KERNEL_SYNC_INFO	*psKernelSyncInfo;
+	IMG_UINT32 ui32Offset;
+	IMG_UINT32 ui32Bytes;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPREG_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	PVRSRV_HWREG sHWReg;
+	IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPREG;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_REGPOL_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	PVRSRV_HWREG sHWReg;
+	IMG_UINT32 ui32Mask;
+	IMG_UINT32 ui32Flags;
+}PVRSRV_BRIDGE_IN_PDUMP_REGPOL;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	PVRSRV_HWREG sHWReg;
+	IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hKernelMemInfo;
+	IMG_DEV_PHYADDR		*pPages;
+	IMG_UINT32			ui32NumPages;
+	IMG_DEV_VIRTADDR	sDevAddr;
+	IMG_UINT32			ui32Start;
+	IMG_UINT32			ui32Length;
+	IMG_BOOL			bContinuous;
+
+}PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_COMMENT_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_CHAR szComment[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
+	IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_COMMENT;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_SETFRAME_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_UINT32 ui32Frame;
+
+}PVRSRV_BRIDGE_IN_PDUMP_SETFRAME;
+
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_BITMAP_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+	IMG_UINT32 ui32FileOffset;
+	IMG_UINT32 ui32Width;
+	IMG_UINT32 ui32Height;
+	IMG_UINT32 ui32StrideInBytes;
+	IMG_DEV_VIRTADDR sDevBaseAddr;
+	IMG_UINT32 ui32Size;
+	PDUMP_PIXEL_FORMAT ePixelFormat;
+	PDUMP_MEM_FORMAT eMemFormat;
+	IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_BITMAP;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_READREG_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+	IMG_UINT32 ui32FileOffset;
+	IMG_UINT32 ui32Address;
+	IMG_UINT32 ui32Size;
+	IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_READREG;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_CHAR szString[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
+	IMG_BOOL bContinuous;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hKernelMemInfo;
+	IMG_UINT32 ui32Offset;
+	IMG_DEV_PHYADDR sPDDevPAddr;
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR;
+
+
+typedef struct PVRSRV_BRIDGE_PDUM_IN_CYCLE_COUNT_REG_READ_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_UINT32 ui32RegOffset;
+	IMG_BOOL bLastFrame;
+}PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUMDEVICE_TAG
+{
+	PVRSRV_ERROR eError;
+	IMG_UINT32 ui32NumDevices;
+	PVRSRV_DEVICE_IDENTIFIER asDeviceIdentifier[PVRSRV_MAX_DEVICES];
+
+}PVRSRV_BRIDGE_OUT_ENUMDEVICE;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO_TAG
+{
+
+	PVRSRV_ERROR		eError;
+	IMG_HANDLE			hDevCookie;
+
+} PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUMCLASS_TAG
+{
+	PVRSRV_ERROR eError;
+	IMG_UINT32 ui32NumDevices;
+	IMG_UINT32 ui32DevID[PVRSRV_MAX_DEVICES];
+
+}PVRSRV_BRIDGE_OUT_ENUMCLASS;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE_TAG
+{
+	IMG_UINT32		ui32BridgeFlags;
+	IMG_UINT32		ui32DeviceID;
+	IMG_HANDLE		hDevCookie;
+
+}PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_HANDLE		hDeviceKM;
+
+}PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	IMG_HANDLE              hDevCookie;
+	IMG_HANDLE				hDevMemContext;
+	IMG_VOID				*pvLinAddr;
+	IMG_SIZE_T              ui32ByteSize;
+	IMG_SIZE_T              ui32PageOffset;
+	IMG_BOOL                bPhysContig;
+	IMG_UINT32				ui32NumPageTableEntries;
+	IMG_SYS_PHYADDR         *psSysPAddr;
+	IMG_UINT32				ui32Flags;
+
+}PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY_TAG
+{
+	PVRSRV_ERROR	eError;
+	PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO	sClientSyncInfo;
+
+}PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hKernelMemInfo;
+	PVRSRV_CLIENT_MEM_INFO	sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY;
+
+
+#define PVRSRV_MAX_DC_DISPLAY_FORMATS			10
+#define PVRSRV_MAX_DC_DISPLAY_DIMENSIONS		10
+#define PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS			4
+#define PVRSRV_MAX_DC_CLIP_RECTS				32
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_UINT32		ui32Count;
+	DISPLAY_FORMAT	asFormat[PVRSRV_MAX_DC_DISPLAY_FORMATS];
+
+}PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS_TAG
+{
+	IMG_UINT32		ui32BridgeFlags;
+	IMG_HANDLE		hDeviceKM;
+	DISPLAY_FORMAT	sFormat;
+
+}PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_UINT32		ui32Count;
+	DISPLAY_DIMS	asDim[PVRSRV_MAX_DC_DISPLAY_DIMENSIONS];
+
+}PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO_TAG
+{
+	PVRSRV_ERROR	eError;
+	DISPLAY_INFO	sDisplayInfo;
+
+}PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_HANDLE		hBuffer;
+
+}PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	IMG_HANDLE				hDeviceKM;
+	IMG_UINT32				ui32Flags;
+	DISPLAY_SURF_ATTRIBUTES	sDstSurfAttrib;
+	DISPLAY_SURF_ATTRIBUTES	sSrcSurfAttrib;
+	IMG_UINT32				ui32BufferCount;
+	IMG_UINT32				ui32OEMFlags;
+	IMG_UINT32				ui32SwapChainID;
+
+} PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN_TAG
+{
+	PVRSRV_ERROR		eError;
+	IMG_HANDLE			hSwapChain;
+	IMG_UINT32			ui32SwapChainID;
+
+} PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDeviceKM;
+	IMG_HANDLE			hSwapChain;
+
+} PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDeviceKM;
+	IMG_HANDLE			hSwapChain;
+	IMG_RECT			sRect;
+
+} PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDeviceKM;
+	IMG_HANDLE			hSwapChain;
+	IMG_UINT32			ui32CKColour;
+
+} PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDeviceKM;
+	IMG_HANDLE			hSwapChain;
+
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS_TAG
+{
+	PVRSRV_ERROR		eError;
+	IMG_UINT32			ui32BufferCount;
+	IMG_HANDLE			ahBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+
+} PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDeviceKM;
+	IMG_HANDLE			hBuffer;
+	IMG_UINT32			ui32SwapInterval;
+	IMG_HANDLE			hPrivateTag;
+	IMG_UINT32			ui32ClipRectCount;
+	IMG_RECT			sClipRect[PVRSRV_MAX_DC_CLIP_RECTS];
+
+} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDeviceKM;
+	IMG_HANDLE			hSwapChain;
+
+} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_UINT32			ui32DeviceID;
+	IMG_HANDLE			hDevCookie;
+
+} PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE_TAG
+{
+	PVRSRV_ERROR		eError;
+	IMG_HANDLE			hDeviceKM;
+
+} PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO_TAG
+{
+	PVRSRV_ERROR		eError;
+	BUFFER_INFO			sBufferInfo;
+
+} PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDeviceKM;
+	IMG_UINT32			ui32BufferIndex;
+
+} PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER_TAG
+{
+	PVRSRV_ERROR		eError;
+	IMG_HANDLE			hBuffer;
+
+} PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO_TAG
+{
+	PVRSRV_ERROR		eError;
+	IMG_UINT32			ui32ClientHeapCount;
+	PVRSRV_HEAP_INFO	sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+
+} PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT_TAG
+{
+	PVRSRV_ERROR		eError;
+	IMG_HANDLE			hDevMemContext;
+	IMG_UINT32			ui32ClientHeapCount;
+	PVRSRV_HEAP_INFO	sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+
+} PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_DEVMEMHEAP_TAG
+{
+	PVRSRV_ERROR		eError;
+	IMG_HANDLE			hDevMemHeap;
+
+} PVRSRV_BRIDGE_OUT_CREATE_DEVMEMHEAP;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM_TAG
+{
+	PVRSRV_ERROR			eError;
+	PVRSRV_KERNEL_MEM_INFO	*psKernelMemInfo;
+	PVRSRV_KERNEL_SYNC_INFO	*psKernelSyncInfo;
+	PVRSRV_CLIENT_MEM_INFO	sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO	sClientSyncInfo;
+
+} PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM_TAG
+{
+	PVRSRV_ERROR			eError;
+	IMG_HANDLE				hMemInfo;
+#if defined(SUPPORT_MEMINFO_IDS)
+	IMG_UINT64				ui64Stamp;
+#endif
+
+} PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAPMEMINFOTOUSER_TAG
+{
+	PVRSRV_ERROR			eError;
+	IMG_PVOID				pvLinAddr;
+	IMG_HANDLE				hMappingInfo;
+
+}PVRSRV_BRIDGE_OUT_MAPMEMINFOTOUSER;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM_TAG
+{
+	PVRSRV_ERROR eError;
+	IMG_SIZE_T ui32Total;
+	IMG_SIZE_T ui32Free;
+	IMG_SIZE_T ui32LargestBlock;
+
+} PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM;
+
+
+#include "pvrmmap.h"
+typedef struct PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA_TAG
+{
+    PVRSRV_ERROR		eError;
+
+
+     IMG_UINT32			ui32MMapOffset;
+
+
+    IMG_UINT32			ui32ByteOffset;
+
+
+    IMG_UINT32 			ui32RealByteSize;
+
+
+    IMG_UINT32			ui32UserVAddr;
+
+} PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA;
+
+typedef struct PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA_TAG
+{
+    PVRSRV_ERROR		eError;
+
+
+    IMG_BOOL			bMUnmap;
+
+
+    IMG_UINT32			ui32UserVAddr;
+
+
+    IMG_UINT32			ui32RealByteSize;
+} PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA;
+
+typedef struct PVRSRV_BRIDGE_IN_GET_MISC_INFO_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	PVRSRV_MISC_INFO	sMiscInfo;
+
+}PVRSRV_BRIDGE_IN_GET_MISC_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_MISC_INFO_TAG
+{
+	PVRSRV_ERROR		eError;
+	PVRSRV_MISC_INFO	sMiscInfo;
+
+}PVRSRV_BRIDGE_OUT_GET_MISC_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_MISC_INFO_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	PVRSRV_MISC_INFO	sMiscInfo;
+
+}PVRSRV_BRIDGE_IN_RELEASE_MISC_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_RELEASE_MISC_INFO_TAG
+{
+	PVRSRV_ERROR		eError;
+	PVRSRV_MISC_INFO	sMiscInfo;
+
+}PVRSRV_BRIDGE_OUT_RELEASE_MISC_INFO;
+
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING_TAG
+{
+	PVRSRV_ERROR eError;
+	IMG_BOOL bIsCapturing;
+
+} PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_FB_STATS_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_SIZE_T ui32Total;
+	IMG_SIZE_T ui32Available;
+
+} PVRSRV_BRIDGE_IN_GET_FB_STATS;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAPPHYSTOUSERSPACE_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDevCookie;
+	IMG_SYS_PHYADDR		sSysPhysAddr;
+	IMG_UINT32			uiSizeInBytes;
+
+} PVRSRV_BRIDGE_IN_MAPPHYSTOUSERSPACE;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAPPHYSTOUSERSPACE_TAG
+{
+	IMG_PVOID			pvUserAddr;
+	IMG_UINT32			uiActualSize;
+	IMG_PVOID			pvProcess;
+
+} PVRSRV_BRIDGE_OUT_MAPPHYSTOUSERSPACE;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAPPHYSTOUSERSPACE_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDevCookie;
+	IMG_PVOID			pvUserAddr;
+	IMG_PVOID			pvProcess;
+
+} PVRSRV_BRIDGE_IN_UNMAPPHYSTOUSERSPACE;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETPHYSTOUSERSPACEMAP_TAG
+{
+	IMG_PVOID			*ppvTbl;
+	IMG_UINT32			uiTblSize;
+
+} PVRSRV_BRIDGE_OUT_GETPHYSTOUSERSPACEMAP;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_REGISTER_SIM_PROCESS_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDevCookie;
+	IMG_PVOID			pvProcess;
+
+} PVRSRV_BRIDGE_IN_REGISTER_SIM_PROCESS;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_REGISTER_SIM_PROCESS_TAG
+{
+	IMG_SYS_PHYADDR		sRegsPhysBase;
+	IMG_VOID			*pvRegsBase;
+	IMG_PVOID			pvProcess;
+	IMG_UINT32			ulNoOfEntries;
+	IMG_PVOID			pvTblLinAddr;
+
+} PVRSRV_BRIDGE_OUT_REGISTER_SIM_PROCESS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNREGISTER_SIM_PROCESS_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDevCookie;
+	IMG_PVOID			pvProcess;
+	IMG_VOID			*pvRegsBase;
+
+} PVRSRV_BRIDGE_IN_UNREGISTER_SIM_PROCESS;
+
+typedef struct PVRSRV_BRIDGE_IN_PROCESS_SIMISR_EVENT_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDevCookie;
+	IMG_UINT32			ui32StatusAndMask;
+	PVRSRV_ERROR 		eError;
+
+} PVRSRV_BRIDGE_IN_PROCESS_SIMISR_EVENT;
+
+typedef struct PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_BOOL			bInitSuccesful;
+} PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+    IMG_UINT32 ui32Flags;
+    IMG_SIZE_T ui32Size;
+}PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM_TAG
+{
+	PVRSRV_ERROR			eError;
+	PVRSRV_KERNEL_MEM_INFO	*psKernelMemInfo;
+	PVRSRV_CLIENT_MEM_INFO	sClientMemInfo;
+}PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	PVRSRV_KERNEL_MEM_INFO	*psKernelMemInfo;
+	PVRSRV_CLIENT_MEM_INFO	sClientMemInfo;
+}PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM_TAG
+{
+	PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hKernelMemInfo;
+}PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM_TAG
+{
+	PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO	sClientSyncInfo;
+	PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+	PVRSRV_KERNEL_SYNC_INFO	*psKernelSyncInfo;
+	PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_MEMINFO_MEM_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+}PVRSRV_BRIDGE_IN_UNMAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_UNMAP_MEMINFO_MEM_TAG
+{
+	PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_UNMAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_GETMMU_PD_DEVPADDR_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+    IMG_HANDLE hDevMemContext;
+}PVRSRV_BRIDGE_IN_GETMMU_PD_DEVPADDR;
+
+typedef struct PVRSRV_BRIDGE_OUT_GETMMU_PD_DEVPADDR_TAG
+{
+    IMG_DEV_PHYADDR sPDDevPAddr;
+	PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_GETMMU_PD_DEVPADDR;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAI_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE	hOSEventKM;
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAIT;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN_TAG
+{
+	PVRSRV_EVENTOBJECT sEventObject;
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN;
+
+typedef struct	PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN_TAG
+{
+	IMG_HANDLE hOSEvent;
+	PVRSRV_ERROR eError;
+} PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE_TAG
+{
+	PVRSRV_EVENTOBJECT sEventObject;
+	IMG_HANDLE hOSEventKM;
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE;
+
+typedef struct PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hKernelSyncInfo;
+	IMG_UINT32 ui32ModifyFlags;
+
+} PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS;
+
+typedef struct PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hKernelSyncInfo;
+	IMG_UINT32 ui32ModifyFlags;
+
+} PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS;
+
+typedef struct PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS_TAG
+{
+	PVRSRV_ERROR eError;
+
+
+	IMG_UINT32 ui32ReadOpsPending;
+	IMG_UINT32 ui32WriteOpsPending;
+
+} PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS;
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/pvr_bridge_km.h b/drivers/gpu/drm/emgd/pvr/services4/include/pvr_bridge_km.h
new file mode 100644
index 0000000..063ffb5
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/pvr_bridge_km.h
@@ -0,0 +1,292 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __PVR_BRIDGE_KM_H_
+#define __PVR_BRIDGE_KM_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "pvr_bridge.h"
+#include "perproc.h"
+
+#if defined(__linux__)
+PVRSRV_ERROR LinuxBridgeInit(IMG_VOID);
+IMG_VOID LinuxBridgeDeInit(IMG_VOID);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
+												   PVRSRV_DEVICE_IDENTIFIER *psDevIdList);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM(IMG_UINT32			uiDevIndex,
+													PVRSRV_DEVICE_TYPE	eDeviceType,
+													IMG_HANDLE			*phDevCookie);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
+													 PVRSRV_QUEUE_INFO **ppsQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie,
+													PVRSRV_HEAP_INFO *psHeapInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE					hDevCookie,
+														 PVRSRV_PER_PROCESS_DATA	*psPerProc,
+														 IMG_HANDLE					*phDevMemContext,
+														 IMG_UINT32					*pui32ClientHeapCount,
+														 PVRSRV_HEAP_INFO			*psHeapInfo,
+														 IMG_BOOL					*pbCreated,
+														 IMG_BOOL					*pbShared);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContextKM(IMG_HANDLE hDevCookie,
+														  IMG_HANDLE hDevMemContext,
+														  IMG_BOOL *pbDestroyed);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE				hDevCookie,
+															IMG_HANDLE			hDevMemContext,
+															IMG_UINT32			*pui32ClientHeapCount,
+															PVRSRV_HEAP_INFO	*psHeapInfo,
+															IMG_BOOL 			*pbShared
+					);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE					hDevCookie,
+												 PVRSRV_PER_PROCESS_DATA	*psPerProc,
+												 IMG_HANDLE					hDevMemHeap,
+												 IMG_UINT32					ui32Flags,
+												 IMG_SIZE_T					ui32Size,
+												 IMG_SIZE_T					ui32Alignment,
+												 PVRSRV_KERNEL_MEM_INFO		**ppsMemInfo);
+
+
+#if defined(PVRSRV_LOG_MEMORY_ALLOCS)
+	#define PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo, logStr) \
+		(PVR_TRACE(("PVRSRVAllocDeviceMemKM(" #devCookie ", " #perProc ", " #devMemHeap ", " #flags ", " #size \
+			", " #alignment "," #memInfo "): " logStr " (size = 0x%;x)", size)),\
+			_PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo))
+#else
+	#define PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo, logStr) \
+			_PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo)
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE			hDevCookie,
+												PVRSRV_KERNEL_MEM_INFO	*psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE			hDevCookie,
+												PVRSRV_KERNEL_MEM_INFO	*psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReserveDeviceVirtualMemKM(IMG_HANDLE		hDevMemHeap,
+														 IMG_DEV_VIRTADDR	*psDevVAddr,
+														 IMG_SIZE_T			ui32Size,
+														 IMG_SIZE_T			ui32Alignment,
+														 PVRSRV_KERNEL_MEM_INFO	**ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceVirtualMemKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+												  PVRSRV_KERNEL_MEM_INFO	*psSrcMemInfo,
+												  IMG_HANDLE				hDstDevMemHeap,
+												  PVRSRV_KERNEL_MEM_INFO	**ppsDstMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE				hDevCookie,
+												PVRSRV_PER_PROCESS_DATA	*psPerProc,
+												IMG_HANDLE				hDevMemContext,
+												IMG_SIZE_T 				ui32ByteSize,
+												IMG_SIZE_T				ui32PageOffset,
+												IMG_BOOL				bPhysContig,
+												IMG_SYS_PHYADDR	 		*psSysAddr,
+												IMG_VOID 				*pvLinAddr,
+												IMG_UINT32				ui32Flags,
+												PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumerateDCKM(PVRSRV_DEVICE_CLASS DeviceClass,
+								 IMG_UINT32 *pui32DevCount,
+								 IMG_UINT32 *pui32DevID );
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVOpenDCDeviceKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+								  IMG_UINT32				ui32DeviceID,
+								  IMG_HANDLE 				hDevCookie,
+								  IMG_HANDLE 				*phDeviceKM);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCloseDCDeviceKM(IMG_HANDLE hDeviceKM, IMG_BOOL bResManCallback);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumDCFormatsKM(IMG_HANDLE hDeviceKM,
+								   IMG_UINT32 *pui32Count,
+								   DISPLAY_FORMAT *psFormat);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumDCDimsKM(IMG_HANDLE hDeviceKM,
+								DISPLAY_FORMAT *psFormat,
+								IMG_UINT32 *pui32Count,
+								DISPLAY_DIMS *psDim);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCSystemBufferKM(IMG_HANDLE hDeviceKM,
+									   IMG_HANDLE *phBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCInfoKM(IMG_HANDLE hDeviceKM,
+							   DISPLAY_INFO *psDisplayInfo);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCreateDCSwapChainKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+									   IMG_HANDLE				hDeviceKM,
+									   IMG_UINT32				ui32Flags,
+									   DISPLAY_SURF_ATTRIBUTES	*psDstSurfAttrib,
+									   DISPLAY_SURF_ATTRIBUTES	*psSrcSurfAttrib,
+									   IMG_UINT32				ui32BufferCount,
+									   IMG_UINT32				ui32OEMFlags,
+									   IMG_HANDLE				*phSwapChain,
+									   IMG_UINT32				*pui32SwapChainID);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(IMG_HANDLE	hSwapChain);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCDstRectKM(IMG_HANDLE	hDeviceKM,
+								  IMG_HANDLE	hSwapChain,
+								  IMG_RECT	*psRect);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCSrcRectKM(IMG_HANDLE	hDeviceKM,
+								  IMG_HANDLE	hSwapChain,
+								  IMG_RECT	*psRect);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(IMG_HANDLE	hDeviceKM,
+									   IMG_HANDLE	hSwapChain,
+									   IMG_UINT32	ui32CKColour);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(IMG_HANDLE	hDeviceKM,
+									IMG_HANDLE		hSwapChain,
+									IMG_UINT32		ui32CKColour);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE	hDeviceKM,
+								  IMG_HANDLE	hSwapChain,
+								  IMG_UINT32	*pui32BufferCount,
+								  IMG_HANDLE	*phBuffer);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE	hDeviceKM,
+									IMG_HANDLE	hBuffer,
+									IMG_UINT32	ui32SwapInterval,
+									IMG_HANDLE	hPrivateTag,
+									IMG_UINT32	ui32ClipRectCount,
+									IMG_RECT	*psClipRect);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE	hDeviceKM,
+									IMG_HANDLE	hSwapChain);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVOpenBCDeviceKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+								  IMG_UINT32				ui32DeviceID,
+								  IMG_HANDLE				hDevCookie,
+								  IMG_HANDLE				*phDeviceKM);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCloseBCDeviceKM(IMG_HANDLE hDeviceKM, IMG_BOOL bResManCallback);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetBCInfoKM(IMG_HANDLE	hDeviceKM,
+							   BUFFER_INFO	*psBufferInfo);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetBCBufferKM(IMG_HANDLE	hDeviceKM,
+								 IMG_UINT32	ui32BufferIndex,
+								 IMG_HANDLE	*phBuffer);
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetBCBufferIdFromTagKM(IMG_HANDLE hDeviceKM,
+								  IMG_UINT32 ui32BufferIndex,
+								  IMG_HANDLE pidx);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+													   IMG_HANDLE				hDevMemContext,
+													   IMG_HANDLE				hDeviceClassBuffer,
+													   PVRSRV_KERNEL_MEM_INFO	**ppsMemInfo,
+													   IMG_HANDLE				*phOSMapInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFreeDeviceMemKM(IMG_UINT32 ui32Flags,
+												   IMG_SIZE_T *pui32Total,
+												   IMG_SIZE_T *pui32Free,
+												   IMG_SIZE_T *pui32LargestBlock);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE					hDevCookie,
+												IMG_HANDLE					hDevMemContext,
+												PVRSRV_KERNEL_SYNC_INFO	**ppsKernelSyncInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO	*psKernelSyncInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo);
+
+PVRSRV_ERROR PVRSRVGetFBStatsKM(IMG_SIZE_T	*pui32Total,
+								IMG_SIZE_T	*pui32Available);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+							 IMG_UINT32 				ui32Flags,
+							 IMG_SIZE_T 				ui32Size,
+							 PVRSRV_KERNEL_MEM_INFO		**ppsKernelMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVFreeSharedSysMemoryKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVDissociateMemFromResmanKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVGetPageListKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo, struct page ***pvPageList,
+	unsigned long *numpages,
+	unsigned long *offset);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/pvrmmap.h b/drivers/gpu/drm/emgd/pvr/services4/include/pvrmmap.h
new file mode 100644
index 0000000..54f1121
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/pvrmmap.h
@@ -0,0 +1,32 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __PVRMMAP_H__
+#define __PVRMMAP_H__
+
+PVRSRV_ERROR PVRPMapKMem(IMG_HANDLE hModule, IMG_VOID **ppvLinAddr, IMG_VOID *pvLinAddrKM, IMG_HANDLE *phMappingInfo, IMG_HANDLE hMHandle);
+
+
+IMG_BOOL PVRUnMapKMem(IMG_HANDLE hModule, IMG_HANDLE hMappingInfo, IMG_HANDLE hMHandle);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/pvrsrv_errors.h b/drivers/gpu/drm/emgd/pvr/services4/include/pvrsrv_errors.h
new file mode 100755
index 0000000..7c8ed47
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/pvrsrv_errors.h
@@ -0,0 +1,189 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__PVRSRV_ERRORS_H__)
+#define __PVRSRV_ERRORS_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+	switch (eError)
+	{
+		case PVRSRV_OK:									return "No Errors";
+		case PVRSRV_ERROR_GENERIC:						return "Generic error - fix";
+		case PVRSRV_ERROR_OUT_OF_MEMORY:				return "PVRSRV_ERROR_OUT_OF_MEMORY - Unable to allocate required memory";
+		case PVRSRV_ERROR_TOO_FEW_BUFFERS:				return "PVRSRV_ERROR_TOO_FEW_BUFFERS";
+		case PVRSRV_ERROR_INVALID_PARAMS:				return "PVRSRV_ERROR_INVALID_PARAMS";
+		case PVRSRV_ERROR_INIT_FAILURE:					return "PVRSRV_ERROR_INIT_FAILURE";
+		case PVRSRV_ERROR_CANT_REGISTER_CALLBACK:		return "PVRSRV_ERROR_CANT_REGISTER_CALLBACK";
+		case PVRSRV_ERROR_INVALID_DEVICE:				return "PVRSRV_ERROR_INVALID_DEVICE";
+		case PVRSRV_ERROR_NOT_OWNER:					return "PVRSRV_ERROR_NOT_OWNER";
+		case PVRSRV_ERROR_BAD_MAPPING:					return "PVRSRV_ERROR_BAD_MAPPING";
+		case PVRSRV_ERROR_TIMEOUT:						return "PVRSRV_ERROR_TIMEOUT";
+		case PVRSRV_ERROR_FLIP_CHAIN_EXISTS:			return "PVRSRV_ERROR_FLIP_CHAIN_EXISTS";
+		case PVRSRV_ERROR_SCENE_INVALID:				return "PVRSRV_ERROR_SCENE_INVALID";
+		case PVRSRV_ERROR_STREAM_ERROR:					return "PVRSRV_ERROR_STREAM_ERROR";
+		case PVRSRV_ERROR_FAILED_DEPENDENCIES:			return "PVRSRV_ERROR_FAILED_DEPENDENCIES";
+		case PVRSRV_ERROR_CMD_NOT_PROCESSED:			return "PVRSRV_ERROR_CMD_NOT_PROCESSED";
+		case PVRSRV_ERROR_CMD_TOO_BIG:					return "PVRSRV_ERROR_CMD_TOO_BIG";
+		case PVRSRV_ERROR_DEVICE_REGISTER_FAILED:		return "PVRSRV_ERROR_DEVICE_REGISTER_FAILED";
+		case PVRSRV_ERROR_TOOMANYBUFFERS:				return "PVRSRV_ERROR_TOOMANYBUFFERS";
+		case PVRSRV_ERROR_NOT_SUPPORTED:				return "PVRSRV_ERROR_NOT_SUPPORTED - fix";
+		case PVRSRV_ERROR_PROCESSING_BLOCKED:			return "PVRSRV_ERROR_PROCESSING_BLOCKED";
+
+		case PVRSRV_ERROR_CANNOT_FLUSH_QUEUE:			return "PVRSRV_ERROR_CANNOT_FLUSH_QUEUE";
+		case PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE:		return "PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE";
+		case PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS:		return "PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS";
+		case PVRSRV_ERROR_RETRY:						return "PVRSRV_ERROR_RETRY";
+
+		case PVRSRV_ERROR_DDK_VERSION_MISMATCH:			return "PVRSRV_ERROR_DDK_VERSION_MISMATCH";
+		case PVRSRV_ERROR_BUILD_MISMATCH:				return "PVRSRV_ERROR_BUILD_MISMATCH";
+
+		case PVRSRV_ERROR_INVALID_FLAGS:				return "PVRSRV_ERROR_INVALID_FLAGS";
+		case PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS:	return "PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS";
+
+		case PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY:		return "PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY";
+		case PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR:			return "PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR";
+		case PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED:		return "PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED";
+
+		case PVRSRV_ERROR_BRIDGE_CALL_FAILED:			return "PVRSRV_ERROR_BRIDGE_CALL_FAILED";
+
+		case PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND:		return "PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND";
+		case PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND:		return "PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND";
+		case PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT:return "PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT";
+
+		case PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND:			return "PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND";
+		case PVRSRV_ERROR_PCI_CALL_FAILED:				return "PVRSRV_ERROR_PCI_CALL_FAILED";
+
+		case PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM:		return "PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM";
+		case PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY:	return "PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY";
+		case PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC:	return "PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC";
+		case PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR:		return "PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR";
+
+		case PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY:	return "PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY";
+		case PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY:	return "PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY";
+
+		case PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES:		return "PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES";
+		case PVRSRV_ERROR_FAILED_TO_FREE_PAGES:			return "PVRSRV_ERROR_FAILED_TO_FREE_PAGES";
+		case PVRSRV_ERROR_FAILED_TO_COPY_PAGES:			return "PVRSRV_ERROR_FAILED_TO_COPY_PAGES";
+		case PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES:			return "PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES";
+		case PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES:		return "PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES";
+		case PVRSRV_ERROR_STILL_MAPPED:					return "PVRSRV_ERROR_STILL_MAPPED";
+		case PVRSRV_ERROR_MAPPING_NOT_FOUND:			return "PVRSRV_ERROR_MAPPING_NOT_FOUND";
+		case PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT:	return "PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT";
+
+		case PVRSRV_ERROR_INVALID_SEGMENT_BLOCK:		return "PVRSRV_ERROR_INVALID_SEGMENT_BLOCK";
+		case PVRSRV_ERROR_INVALID_SGXDEVDATA:			return "PVRSRV_ERROR_INVALID_SGXDEVDATA";
+		case PVRSRV_ERROR_INVALID_DEVINFO:				return "PVRSRV_ERROR_INVALID_DEVINFO";
+		case PVRSRV_ERROR_INVALID_MEMINFO:				return "PVRSRV_ERROR_INVALID_MEMINFO";
+		case PVRSRV_ERROR_UNKNOWN_IOCTL:				return "PVRSRV_ERROR_UNKNOWN_IOCTL";
+		case PVRSRV_ERROR_INVALID_KERNELINFO:			return "PVRSRV_ERROR_INVALID_KERNELINFO";
+		case PVRSRV_ERROR_UNKNOWN_POWER_STATE:			return "PVRSRV_ERROR_UNKNOWN_POWER_STATE";
+		case PVRSRV_ERROR_INVALID_HANDLE_TYPE:			return "PVRSRV_ERROR_INVALID_HANDLE_TYPE";
+		case PVRSRV_ERROR_INVALID_WRAP_TYPE:			return "PVRSRV_ERROR_INVALID_WRAP_TYPE";
+		case PVRSRV_ERROR_INVALID_PHYS_ADDR:			return "PVRSRV_ERROR_INVALID_PHYS_ADDR";
+		case PVRSRV_ERROR_INVALID_HEAPINFO:				return "PVRSRV_ERROR_INVALID_HEAPINFO";
+		case PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO:	return "PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO";
+		case PVRSRV_ERROR_INVALID_MAP_REQUEST:			return "PVRSRV_ERROR_INVALID_MAP_REQUEST";
+		case PVRSRV_ERROR_INVALID_UNMAP_REQUEST:		return "PVRSRV_ERROR_INVALID_UNMAP_REQUEST";
+
+		case PVRSRV_ERROR_EXCEEDED_HW_LIMITS:			return "PVRSRV_ERROR_EXCEEDED_HW_LIMITS";
+		case PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED:	return "PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED";
+
+		case PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA:return "PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA";
+		case PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT:		return "PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT";
+		case PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT:		return "PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT";
+		case PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT:		return "PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT";
+		case PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT:		return "PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT";
+		case PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD:		return "PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD";
+		case PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD:		return "PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD";
+		case PVRSRV_ERROR_THREAD_READ_ERROR:			return "PVRSRV_ERROR_THREAD_READ_ERROR";
+		case PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER:return "PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER";
+		case PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR:		return "PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR";
+		case PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR:		return "PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR";
+		case PVRSRV_ERROR_ISR_ALREADY_INSTALLED:		return "PVRSRV_ERROR_ISR_ALREADY_INSTALLED";
+		case PVRSRV_ERROR_ISR_NOT_INSTALLED:			return "PVRSRV_ERROR_ISR_NOT_INSTALLED";
+		case PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT:return "PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT";
+		case PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO:		return "PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO";
+		case PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT:	return "PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT";
+		case PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES :	return "PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES";
+
+		case PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE:		return "PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE";
+		case PVRSRV_ERROR_INVALID_LOCK_ID:				return "PVRSRV_ERROR_INVALID_LOCK_ID";
+		case PVRSRV_ERROR_RESOURCE_NOT_LOCKED:			return "PVRSRV_ERROR_RESOURCE_NOT_LOCKED";
+
+		case PVRSRV_ERROR_FLIP_FAILED:					return "PVRSRV_ERROR_FLIP_FAILED";
+		case PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED:		return "PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED";
+
+		case PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE:	return "PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE";
+
+		case PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED:	return "PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED";
+		case PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG:			return "PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG";
+		case PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG:	return "PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG";
+		case PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG:		return "PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG";
+
+		case PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID:	return "PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID";
+
+		case PVRSRV_ERROR_PDUMP_NOT_AVAILABLE:			return "PVRSRV_ERROR_PDUMP_NOT_AVAILABLE";
+		case PVRSRV_ERROR_PDUMP_BUFFER_FULL:			return "PVRSRV_ERROR_PDUMP_BUFFER_FULL";
+		case PVRSRV_ERROR_PDUMP_BUF_OVERFLOW:			return "PVRSRV_ERROR_PDUMP_BUF_OVERFLOW";
+		case PVRSRV_ERROR_PDUMP_NOT_ACTIVE:				return "PVRSRV_ERROR_PDUMP_NOT_ACTIVE";
+		case PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES:return "PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES";
+
+		case PVRSRV_ERROR_MUTEX_DESTROY_FAILED:			return "PVRSRV_ERROR_MUTEX_DESTROY_FAILED";
+		case PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR:	return "PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR";
+
+		case PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE:	return "PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE";
+
+		case PVRSRV_ERROR_PROCESS_NOT_INITIALISED:		return "PVRSRV_ERROR_PROCESS_NOT_INITIALISED";
+		case PVRSRV_ERROR_PROCESS_NOT_FOUND:			return "PVRSRV_ERROR_PROCESS_NOT_FOUND";
+		case PVRSRV_ERROR_SRV_CONNECT_FAILED:			return "PVRSRV_ERROR_SRV_CONNECT_FAILED";
+		case PVRSRV_ERROR_SRV_DISCONNECT_FAILED:		return "PVRSRV_ERROR_SRV_DISCONNECT_FAILED";
+		case PVRSRV_ERROR_DEINT_PHASE_FAILED:			return "PVRSRV_ERROR_DEINT_PHASE_FAILED";
+		case PVRSRV_ERROR_INIT2_PHASE_FAILED:			return "PVRSRV_ERROR_INIT2_PHASE_FAILED";
+
+		case PVRSRV_ERROR_NO_DC_DEVICES_FOUND:			return "PVRSRV_ERROR_NO_DC_DEVICES_FOUND";
+		case PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE:		return "PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE";
+		case PVRSRV_ERROR_NO_DEVICEDATA_FOUND:			return "PVRSRV_ERROR_NO_DEVICEDATA_FOUND";
+
+		case PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT:			return "PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT";
+
+		case PVRSRV_ERROR_UNABLE_TO_INIT_TASK:			return "PVRSRV_ERROR_UNABLE_TO_INIT_TASK";
+		case PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK:		return "PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK";
+		case PVRSRV_ERROR_UNABLE_TO_KILL_TASK:			return "PVRSRV_ERROR_UNABLE_TO_KILL_TASK";
+
+		case PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER:		return "PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER";
+		case PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER:		return "PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER";
+		case PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER:		return "PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER";
+
+		case PVRSRV_ERROR_FORCE_I32:					return "PVRSRV_ERROR_FORCE_I32";
+
+		default:
+			return "Unknown PVRSRV error number";
+	}
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/servicesint.h b/drivers/gpu/drm/emgd/pvr/services4/include/servicesint.h
new file mode 100644
index 0000000..4ef3939
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/servicesint.h
@@ -0,0 +1,272 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__SERVICESINT_H__)
+#define __SERVICESINT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "services.h"
+#include "sysinfo.h"
+
+#define HWREC_DEFAULT_TIMEOUT	(500)
+
+#define DRIVERNAME_MAXLENGTH	(100)
+
+typedef enum _PVRSRV_MEMTYPE_
+{
+	PVRSRV_MEMTYPE_UNKNOWN		= 0,
+	PVRSRV_MEMTYPE_DEVICE		= 1,
+	PVRSRV_MEMTYPE_DEVICECLASS	= 2,
+	PVRSRV_MEMTYPE_WRAPPED		= 3,
+	PVRSRV_MEMTYPE_MAPPED		= 4,
+}
+PVRSRV_MEMTYPE;
+
+typedef struct _PVRSRV_KERNEL_MEM_INFO_
+{
+
+	IMG_PVOID				pvLinAddrKM;
+
+
+	IMG_DEV_VIRTADDR		sDevVAddr;
+
+
+	IMG_UINT32				ui32Flags;
+
+
+	IMG_SIZE_T				ui32AllocSize;
+
+
+	PVRSRV_MEMBLK			sMemBlk;
+
+
+	IMG_PVOID				pvSysBackupBuffer;
+
+
+	IMG_UINT32				ui32RefCount;
+
+
+	IMG_BOOL				bPendingFree;
+
+
+	#if defined(SUPPORT_MEMINFO_IDS)
+	#if !defined(USE_CODE)
+
+	IMG_UINT64				ui64Stamp;
+	#else
+	IMG_UINT32				dummy1;
+	IMG_UINT32				dummy2;
+	#endif
+	#endif
+
+
+	struct _PVRSRV_KERNEL_SYNC_INFO_	*psKernelSyncInfo;
+
+	PVRSRV_MEMTYPE			memType;
+
+} PVRSRV_KERNEL_MEM_INFO;
+
+
+typedef struct _PVRSRV_KERNEL_SYNC_INFO_
+{
+
+	PVRSRV_SYNC_DATA		*psSyncData;
+
+
+	IMG_DEV_VIRTADDR		sWriteOpsCompleteDevVAddr;
+
+
+	IMG_DEV_VIRTADDR		sReadOpsCompleteDevVAddr;
+
+
+	PVRSRV_KERNEL_MEM_INFO	*psSyncDataMemInfoKM;
+
+
+	IMG_HANDLE				hResItem;
+
+
+
+        IMG_UINT32              ui32RefCount;
+
+} PVRSRV_KERNEL_SYNC_INFO;
+
+typedef struct _PVRSRV_DEVICE_SYNC_OBJECT_
+{
+
+	IMG_UINT32			ui32ReadOpsPendingVal;
+	IMG_DEV_VIRTADDR	sReadOpsCompleteDevVAddr;
+	IMG_UINT32			ui32WriteOpsPendingVal;
+	IMG_DEV_VIRTADDR	sWriteOpsCompleteDevVAddr;
+} PVRSRV_DEVICE_SYNC_OBJECT;
+
+typedef struct _PVRSRV_SYNC_OBJECT
+{
+	PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfoKM;
+	IMG_UINT32				ui32WriteOpsPending;
+	IMG_UINT32				ui32ReadOpsPending;
+
+}PVRSRV_SYNC_OBJECT, *PPVRSRV_SYNC_OBJECT;
+
+typedef struct _PVRSRV_COMMAND
+{
+	IMG_SIZE_T			ui32CmdSize;
+	IMG_UINT32			ui32DevIndex;
+	IMG_UINT32			CommandType;
+	IMG_UINT32			ui32DstSyncCount;
+	IMG_UINT32			ui32SrcSyncCount;
+	PVRSRV_SYNC_OBJECT	*psDstSync;
+	PVRSRV_SYNC_OBJECT	*psSrcSync;
+	IMG_SIZE_T			ui32DataSize;
+	IMG_UINT32			ui32ProcessID;
+	IMG_VOID			*pvData;
+}PVRSRV_COMMAND, *PPVRSRV_COMMAND;
+
+
+typedef struct _PVRSRV_QUEUE_INFO_
+{
+	IMG_VOID			*pvLinQueueKM;
+	IMG_VOID			*pvLinQueueUM;
+	volatile IMG_SIZE_T	ui32ReadOffset;
+	volatile IMG_SIZE_T	ui32WriteOffset;
+	IMG_UINT32			*pui32KickerAddrKM;
+	IMG_UINT32			*pui32KickerAddrUM;
+	IMG_SIZE_T			ui32QueueSize;
+
+	IMG_UINT32			ui32ProcessID;
+
+	IMG_HANDLE			hMemBlock[2];
+
+	struct _PVRSRV_QUEUE_INFO_ *psNextKM;
+}PVRSRV_QUEUE_INFO;
+
+typedef PVRSRV_ERROR (*PFN_INSERT_CMD) (PVRSRV_QUEUE_INFO*,
+										PVRSRV_COMMAND**,
+										IMG_UINT32,
+										IMG_UINT16,
+										IMG_UINT32,
+										PVRSRV_KERNEL_SYNC_INFO*[],
+										IMG_UINT32,
+										PVRSRV_KERNEL_SYNC_INFO*[],
+										IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_SUBMIT_CMD) (PVRSRV_QUEUE_INFO*, PVRSRV_COMMAND*, IMG_BOOL);
+
+
+typedef struct PVRSRV_DEVICECLASS_BUFFER_TAG
+{
+	PFN_GET_BUFFER_ADDR		pfnGetBufferAddr;
+	IMG_HANDLE				hDevMemContext;
+	IMG_HANDLE				hExtDevice;
+	IMG_HANDLE				hExtBuffer;
+	PVRSRV_KERNEL_SYNC_INFO	*psKernelSyncInfo;
+
+} PVRSRV_DEVICECLASS_BUFFER;
+
+
+typedef struct PVRSRV_CLIENT_DEVICECLASS_INFO_TAG
+{
+	IMG_HANDLE hDeviceKM;
+	IMG_HANDLE	hServices;
+} PVRSRV_CLIENT_DEVICECLASS_INFO;
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetWriteOpsPending)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetWriteOpsPending(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
+{
+	IMG_UINT32 ui32WriteOpsPending;
+
+	if(bIsReadOp)
+	{
+		ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
+	}
+	else
+	{
+
+
+
+		ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+	}
+
+	return ui32WriteOpsPending;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetReadOpsPending)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetReadOpsPending(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
+{
+	IMG_UINT32 ui32ReadOpsPending;
+
+	if(bIsReadOp)
+	{
+		ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+	}
+	else
+	{
+		ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending;
+	}
+
+	return ui32ReadOpsPending;
+}
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVQueueCommand(IMG_HANDLE hQueueInfo,
+								PVRSRV_COMMAND *psCommand);
+
+
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVGetMMUContextPDDevPAddr(const PVRSRV_CONNECTION *psConnection,
+                              IMG_HANDLE hDevMemContext,
+                              IMG_DEV_PHYADDR *sPDDevPAddr);
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVAllocSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+						IMG_UINT32 ui32Flags,
+						IMG_SIZE_T ui32Size,
+						PVRSRV_CLIENT_MEM_INFO **ppsClientMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVFreeSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+					   PVRSRV_CLIENT_MEM_INFO *psClientMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVUnrefSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+                        PVRSRV_CLIENT_MEM_INFO *psClientMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVMapMemInfoMem(const PVRSRV_CONNECTION *psConnection,
+                    IMG_HANDLE hKernelMemInfo,
+                    PVRSRV_CLIENT_MEM_INFO **ppsClientMemInfo);
+
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/sgx_bridge.h b/drivers/gpu/drm/emgd/pvr/services4/include/sgx_bridge.h
new file mode 100644
index 0000000..61a147c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/sgx_bridge.h
@@ -0,0 +1,473 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__SGX_BRIDGE_H__)
+#define __SGX_BRIDGE_H__
+
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "pvr_bridge.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+#define PVRSRV_BRIDGE_SGX_CMD_BASE (PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD+1)
+#define PVRSRV_BRIDGE_SGX_GETCLIENTINFO			PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+0)
+#define PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO		PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+1)
+#define PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+2)
+#define PVRSRV_BRIDGE_SGX_DOKICK				PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+3)
+#define PVRSRV_BRIDGE_SGX_GETPHYSPAGEADDR		PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+4)
+#define PVRSRV_BRIDGE_SGX_READREGISTRYDWORD		PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+5)
+
+#define PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE   PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+9)
+
+#define PVRSRV_BRIDGE_SGX_GETMMUPDADDR  		PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+10)
+
+#if defined(TRANSFER_QUEUE)
+#define PVRSRV_BRIDGE_SGX_SUBMITTRANSFER			PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+13)
+#endif
+#define PVRSRV_BRIDGE_SGX_GETMISCINFO				PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+14)
+#define PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT			PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+15)
+#define PVRSRV_BRIDGE_SGX_DEVINITPART2				PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+16)
+
+#define PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC			PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+17)
+#define PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC			PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+18)
+#define PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC			PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+19)
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+20)
+#define PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+21)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+22)
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define PVRSRV_BRIDGE_SGX_SUBMIT2D					PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+23)
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+24)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+25)
+#endif
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+26)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+27)
+
+#define PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES		PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+28)
+
+#if defined(SUPPORT_SGX_HWPERF)
+#define PVRSRV_BRIDGE_SGX_READ_DIFF_COUNTERS		PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+29)
+#define PVRSRV_BRIDGE_SGX_READ_HWPERF_CB			PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+30)
+#endif
+
+#if defined(PDUMP)
+#define PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY		PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+31)
+#define PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+32)
+#define PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+33)
+#define PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+34)
+#define PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB				PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+35)
+#endif
+
+
+
+#define PVRSRV_BRIDGE_LAST_SGX_CMD (PVRSRV_BRIDGE_SGX_CMD_BASE+35)
+
+
+typedef struct PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hDevMemHeap;
+	IMG_DEV_VIRTADDR sDevVAddr;
+}PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR
+{
+	PVRSRV_ERROR		eError;
+	IMG_DEV_PHYADDR		DevPAddr;
+	IMG_CPU_PHYADDR		CpuPAddr;
+}PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_GETMMU_PDADDR_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	IMG_HANDLE				hDevCookie;
+	IMG_HANDLE				hDevMemContext;
+}PVRSRV_BRIDGE_IN_SGX_GETMMU_PDADDR;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_GETMMU_PDADDR_TAG
+{
+	IMG_DEV_PHYADDR 		sPDDevPAddr;
+	PVRSRV_ERROR			eError;
+}PVRSRV_BRIDGE_OUT_SGX_GETMMU_PDADDR;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GETCLIENTINFO_TAG
+{
+	IMG_UINT32					ui32BridgeFlags;
+	IMG_HANDLE					hDevCookie;
+}PVRSRV_BRIDGE_IN_GETCLIENTINFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO_TAG
+{
+	SGX_INTERNAL_DEVINFO	sSGXInternalDevInfo;
+	PVRSRV_ERROR				eError;
+}PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	IMG_HANDLE				hDevCookie;
+}PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETCLIENTINFO_TAG
+{
+	SGX_CLIENT_INFO  	sClientInfo;
+	PVRSRV_ERROR			eError;
+}PVRSRV_BRIDGE_OUT_GETCLIENTINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASECLIENTINFO_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	IMG_HANDLE				hDevCookie;
+	SGX_CLIENT_INFO  	sClientInfo;
+}PVRSRV_BRIDGE_IN_RELEASECLIENTINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ISPBREAKPOLL_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	IMG_HANDLE				hDevCookie;
+}PVRSRV_BRIDGE_IN_ISPBREAKPOLL;
+
+
+typedef struct PVRSRV_BRIDGE_IN_DOKICK_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	IMG_HANDLE				hDevCookie;
+	SGX_CCB_KICK			sCCBKick;
+}PVRSRV_BRIDGE_IN_DOKICK;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	IMG_HANDLE				hDevCookie;
+}PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES;
+
+
+#if defined(TRANSFER_QUEUE)
+
+typedef struct PVRSRV_BRIDGE_IN_SUBMITTRANSFER_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	IMG_HANDLE				hDevCookie;
+	PVRSRV_TRANSFER_SGX_KICK 			sKick;
+}PVRSRV_BRIDGE_IN_SUBMITTRANSFER;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+
+typedef struct PVRSRV_BRIDGE_IN_SUBMIT2D_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	IMG_HANDLE				hDevCookie;
+	PVRSRV_2D_SGX_KICK 				sKick;
+} PVRSRV_BRIDGE_IN_SUBMIT2D;
+#endif
+#endif
+
+
+typedef struct PVRSRV_BRIDGE_IN_READREGDWORD_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	IMG_HANDLE				hDevCookie;
+    IMG_PCHAR				pszKey;
+    IMG_PCHAR				pszValue;
+}PVRSRV_BRIDGE_IN_READREGDWORD;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_READREGDWORD_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_UINT32		ui32Data;
+}PVRSRV_BRIDGE_OUT_READREGDWORD;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGXGETMISCINFO_TAG
+{
+	IMG_UINT32		ui32BridgeFlags;
+	IMG_HANDLE		hDevCookie;
+	SGX_MISC_INFO	*psMiscInfo;
+}PVRSRV_BRIDGE_IN_SGXGETMISCINFO;
+
+typedef struct PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT_TAG
+{
+	IMG_UINT32		ui32BridgeFlags;
+	IMG_HANDLE		hDevCookie;
+}PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT_TAG
+{
+	PVRSRV_ERROR			eError;
+	SGX_BRIDGE_INFO_FOR_SRVINIT	sInitInfo;
+}PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGXDEVINITPART2_TAG
+{
+	IMG_UINT32		ui32BridgeFlags;
+	IMG_HANDLE		hDevCookie;
+	SGX_BRIDGE_INIT_INFO	sInitInfo;
+}PVRSRV_BRIDGE_IN_SGXDEVINITPART2;
+
+
+typedef struct PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE_TAG
+{
+	IMG_UINT32				ui32BridgeFlags;
+	IMG_HANDLE				hDevCookie;
+	IMG_HANDLE				hKernSyncInfo;
+	IMG_BOOL				bWaitForComplete;
+}PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE;
+
+
+#define PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS 10
+
+typedef struct PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hDevCookie;
+	IMG_BOOL bLockOnFailure;
+	IMG_UINT32 ui32TotalPBSize;
+}PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC_TAG
+{
+	IMG_HANDLE hKernelMemInfo;
+	IMG_HANDLE hSharedPBDesc;
+	IMG_HANDLE hSharedPBDescKernelMemInfoHandle;
+	IMG_HANDLE hHWPBDescKernelMemInfoHandle;
+	IMG_HANDLE hBlockKernelMemInfoHandle;
+	IMG_HANDLE hHWBlockKernelMemInfoHandle;
+	IMG_HANDLE ahSharedPBDescSubKernelMemInfoHandles[PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS];
+	IMG_UINT32 ui32SharedPBDescSubKernelMemInfoHandlesCount;
+	PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hSharedPBDesc;
+}PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC_TAG
+{
+	PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hDevCookie;
+	IMG_HANDLE hSharedPBDescKernelMemInfo;
+	IMG_HANDLE hHWPBDescKernelMemInfo;
+	IMG_HANDLE hBlockKernelMemInfo;
+	IMG_HANDLE hHWBlockKernelMemInfo;
+	IMG_UINT32 ui32TotalPBSize;
+	IMG_HANDLE *phKernelMemInfoHandles;
+	IMG_UINT32 ui32KernelMemInfoHandlesCount;
+}PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC_TAG
+{
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hSharedPBDesc;
+}PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC;
+
+
+#ifdef	PDUMP
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	SGX_KICKTA_DUMP_BUFFER *psBufferArray;
+	IMG_UINT32 ui32BufferArrayLength;
+	IMG_BOOL bDumpPolls;
+} PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hDevCookie;
+	IMG_UINT32 ui32DumpFrameNum;
+	IMG_BOOL bLastFrame;
+	IMG_UINT32 *pui32Registers;
+	IMG_UINT32 ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMPCOUNTER_REGISTERS_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_UINT32 ui32DumpFrameNum;
+	IMG_BOOL bLastFrame;
+	IMG_UINT32 *pui32Registers;
+	IMG_UINT32 ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hDevCookie;
+	IMG_UINT32 ui32DumpFrameNum;
+	IMG_UINT32 ui32TAKickCount;
+	IMG_BOOL bLastFrame;
+	IMG_UINT32 *pui32Registers;
+	IMG_UINT32 ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB_TAG
+{
+	IMG_UINT32			ui32BridgeFlags;
+	IMG_HANDLE			hDevCookie;
+	IMG_CHAR			szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+	IMG_UINT32			ui32FileOffset;
+	IMG_UINT32			ui32PDumpFlags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB;
+
+#endif
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hDevCookie;
+	IMG_DEV_VIRTADDR sHWRenderContextDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT_TAG
+{
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hHWRenderContext;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hDevCookie;
+	IMG_HANDLE hHWRenderContext;
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hDevCookie;
+	IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hHWTransferContext;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hDevCookie;
+	IMG_HANDLE hHWTransferContext;
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hDevCookie;
+	IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET;
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hDevCookie;
+	IMG_DEV_VIRTADDR sHW2DContextDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT_TAG
+{
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hHW2DContext;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT_TAG
+{
+	IMG_UINT32 ui32BridgeFlags;
+	IMG_HANDLE hDevCookie;
+	IMG_HANDLE hHW2DContext;
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT;
+
+#define	SGX2D_MAX_BLT_CMD_SIZ		256
+#endif
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_READ_DIFF_COUNTERS_TAG
+{
+	IMG_UINT32		ui32BridgeFlags;
+	IMG_HANDLE		hDevCookie;
+	IMG_UINT32		ui32Reg;
+	IMG_BOOL		bNew;
+	IMG_UINT32		ui32New;
+	IMG_UINT32		ui32NewReset;
+	IMG_UINT32		ui32CountersReg;
+	IMG_UINT32		ui32Reg2;
+} PVRSRV_BRIDGE_IN_SGX_READ_DIFF_COUNTERS;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_READ_DIFF_COUNTERS_TAG
+{
+	PVRSRV_ERROR				eError;
+	IMG_UINT32					ui32Old;
+	IMG_BOOL					bActive;
+	PVRSRV_SGXDEV_DIFF_INFO		sDiffs;
+} PVRSRV_BRIDGE_OUT_SGX_READ_DIFF_COUNTERS;
+
+
+#if defined(SUPPORT_SGX_HWPERF)
+typedef struct PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB_TAG
+{
+	IMG_UINT32					ui32BridgeFlags;
+	IMG_HANDLE					hDevCookie;
+	IMG_UINT32					ui32ArraySize;
+	PVRSRV_SGX_HWPERF_CB_ENTRY	*psHWPerfCBData;
+} PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB_TAG
+{
+	PVRSRV_ERROR		eError;
+	IMG_UINT32			ui32DataCount;
+	IMG_UINT32			ui32ClockSpeed;
+	IMG_UINT32			ui32HostTimeStamp;
+} PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB;
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/sgx_mkif_km.h b/drivers/gpu/drm/emgd/pvr/services4/include/sgx_mkif_km.h
new file mode 100644
index 0000000..7a59274
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/sgx_mkif_km.h
@@ -0,0 +1,339 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__SGX_MKIF_KM_H__)
+#define __SGX_MKIF_KM_H__
+
+#include "img_types.h"
+#include "servicesint.h"
+#include "sgxapi_km.h"
+
+
+#if defined(SGX_FEATURE_MP)
+	#define SGX_REG_BANK_SHIFT 			(12)
+	#define SGX_REG_BANK_SIZE 			(0x4000)
+	#if defined(SGX541)
+		#define SGX_REG_BANK_BASE_INDEX		(1)
+		#define	SGX_REG_BANK_MASTER_INDEX	(SGX_REG_BANK_BASE_INDEX + SGX_FEATURE_MP_CORE_COUNT)
+	#else
+		#define SGX_REG_BANK_BASE_INDEX		(2)
+		#define	SGX_REG_BANK_MASTER_INDEX	(1)
+	#endif
+	#define SGX_MP_CORE_SELECT(x,i) 	(x + ((i + SGX_REG_BANK_BASE_INDEX) * SGX_REG_BANK_SIZE))
+	#define SGX_MP_MASTER_SELECT(x) 	(x + (SGX_REG_BANK_MASTER_INDEX * SGX_REG_BANK_SIZE))
+#else
+	#define SGX_MP_CORE_SELECT(x,i) 	(x)
+#endif
+
+
+typedef struct _SGXMKIF_COMMAND_
+{
+	IMG_UINT32				ui32ServiceAddress;
+	IMG_UINT32				ui32CacheControl;
+	IMG_UINT32				ui32Data[2];
+} SGXMKIF_COMMAND;
+
+
+typedef struct _PVRSRV_SGX_KERNEL_CCB_
+{
+	SGXMKIF_COMMAND		asCommands[256];
+} PVRSRV_SGX_KERNEL_CCB;
+
+
+typedef struct _PVRSRV_SGX_CCB_CTL_
+{
+	IMG_UINT32				ui32WriteOffset;
+	IMG_UINT32				ui32ReadOffset;
+} PVRSRV_SGX_CCB_CTL;
+
+
+typedef struct _SGXMKIF_HOST_CTL_
+{
+#if defined(PVRSRV_USSE_EDM_BREAKPOINTS)
+	IMG_UINT32				ui32BreakpointDisable;
+	IMG_UINT32				ui32Continue;
+#endif
+
+	volatile IMG_UINT32		ui32InitStatus;
+	volatile IMG_UINT32		ui32PowerStatus;
+	volatile IMG_UINT32		ui32CleanupStatus;
+#if defined(FIX_HW_BRN_28889)
+	volatile IMG_UINT32		ui32InvalStatus;
+#endif
+#if defined(SUPPORT_HW_RECOVERY)
+	IMG_UINT32				ui32uKernelDetectedLockups;
+	IMG_UINT32				ui32HostDetectedLockups;
+	IMG_UINT32				ui32HWRecoverySampleRate;
+#endif
+	IMG_UINT32				ui32uKernelTimerClock;
+	IMG_UINT32				ui32ActivePowManSampleRate;
+	IMG_UINT32				ui32InterruptFlags;
+	IMG_UINT32				ui32InterruptClearFlags;
+
+
+	IMG_UINT32				ui32NumActivePowerEvents;
+
+#if defined(SUPPORT_SGX_HWPERF)
+	IMG_UINT32			ui32HWPerfFlags;
+#endif
+
+
+	IMG_UINT32			ui32TimeWraps;
+} SGXMKIF_HOST_CTL;
+
+#define	SGXMKIF_CMDTA_CTRLFLAGS_READY			0x00000001
+typedef struct _SGXMKIF_CMDTA_SHARED_
+{
+	IMG_UINT32			ui32CtrlFlags;
+
+	IMG_UINT32			ui32NumTAStatusVals;
+	IMG_UINT32			ui32Num3DStatusVals;
+
+
+	IMG_UINT32			ui32TATQSyncWriteOpsPendingVal;
+	IMG_DEV_VIRTADDR	sTATQSyncWriteOpsCompleteDevVAddr;
+	IMG_UINT32			ui32TATQSyncReadOpsPendingVal;
+	IMG_DEV_VIRTADDR	sTATQSyncReadOpsCompleteDevVAddr;
+
+
+	IMG_UINT32			ui323DTQSyncWriteOpsPendingVal;
+	IMG_DEV_VIRTADDR	s3DTQSyncWriteOpsCompleteDevVAddr;
+	IMG_UINT32			ui323DTQSyncReadOpsPendingVal;
+	IMG_DEV_VIRTADDR	s3DTQSyncReadOpsCompleteDevVAddr;
+
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+	IMG_UINT32					ui32NumTASrcSyncs;
+	PVRSRV_DEVICE_SYNC_OBJECT	asTASrcSyncs[SGX_MAX_TA_SRC_SYNCS];
+	IMG_UINT32					ui32NumTADstSyncs;
+	PVRSRV_DEVICE_SYNC_OBJECT	asTADstSyncs[SGX_MAX_TA_DST_SYNCS];
+	IMG_UINT32					ui32Num3DSrcSyncs;
+	PVRSRV_DEVICE_SYNC_OBJECT	as3DSrcSyncs[SGX_MAX_3D_SRC_SYNCS];
+#else
+
+	IMG_UINT32			ui32NumSrcSyncs;
+	PVRSRV_DEVICE_SYNC_OBJECT	asSrcSyncs[SGX_MAX_SRC_SYNCS];
+#endif
+
+
+	PVRSRV_DEVICE_SYNC_OBJECT	sTA3DDependency;
+
+	CTL_STATUS			sCtlTAStatusInfo[SGX_MAX_TA_STATUS_VALS];
+	CTL_STATUS			sCtl3DStatusInfo[SGX_MAX_3D_STATUS_VALS];
+
+} SGXMKIF_CMDTA_SHARED;
+
+#define SGXTQ_MAX_STATUS						SGX_MAX_TRANSFER_STATUS_VALS + 2
+
+#define SGXMKIF_TQFLAGS_NOSYNCUPDATE			0x00000001
+#define SGXMKIF_TQFLAGS_KEEPPENDING				0x00000002
+#define SGXMKIF_TQFLAGS_TATQ_SYNC				0x00000004
+#define SGXMKIF_TQFLAGS_3DTQ_SYNC				0x00000008
+#if defined(SGX_FEATURE_FAST_RENDER_CONTEXT_SWITCH)
+#define SGXMKIF_TQFLAGS_CTXSWITCH				0x00000010
+#endif
+#define SGXMKIF_TQFLAGS_DUMMYTRANSFER			0x00000020
+
+typedef struct _SGXMKIF_TRANSFERCMD_SHARED_
+{
+
+
+	IMG_UINT32		ui32SrcReadOpPendingVal;
+	IMG_DEV_VIRTADDR	sSrcReadOpsCompleteDevAddr;
+
+	IMG_UINT32		ui32SrcWriteOpPendingVal;
+	IMG_DEV_VIRTADDR	sSrcWriteOpsCompleteDevAddr;
+
+
+
+	IMG_UINT32		ui32DstReadOpPendingVal;
+	IMG_DEV_VIRTADDR	sDstReadOpsCompleteDevAddr;
+
+	IMG_UINT32		ui32DstWriteOpPendingVal;
+	IMG_DEV_VIRTADDR	sDstWriteOpsCompleteDevAddr;
+
+
+	IMG_UINT32		ui32TASyncWriteOpsPendingVal;
+	IMG_DEV_VIRTADDR	sTASyncWriteOpsCompleteDevVAddr;
+	IMG_UINT32		ui32TASyncReadOpsPendingVal;
+	IMG_DEV_VIRTADDR	sTASyncReadOpsCompleteDevVAddr;
+
+
+	IMG_UINT32		ui323DSyncWriteOpsPendingVal;
+	IMG_DEV_VIRTADDR	s3DSyncWriteOpsCompleteDevVAddr;
+	IMG_UINT32		ui323DSyncReadOpsPendingVal;
+	IMG_DEV_VIRTADDR	s3DSyncReadOpsCompleteDevVAddr;
+
+	IMG_UINT32 		ui32NumStatusVals;
+	CTL_STATUS  	sCtlStatusInfo[SGXTQ_MAX_STATUS];
+} SGXMKIF_TRANSFERCMD_SHARED, *PSGXMKIF_TRANSFERCMD_SHARED;
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _SGXMKIF_2DCMD_SHARED_ {
+
+	IMG_UINT32			ui32NumSrcSync;
+	PVRSRV_DEVICE_SYNC_OBJECT	sSrcSyncData[SGX_MAX_2D_SRC_SYNC_OPS];
+
+
+	PVRSRV_DEVICE_SYNC_OBJECT	sDstSyncData;
+
+
+	PVRSRV_DEVICE_SYNC_OBJECT	sTASyncData;
+
+
+	PVRSRV_DEVICE_SYNC_OBJECT	s3DSyncData;
+} SGXMKIF_2DCMD_SHARED, *PSGXMKIF_2DCMD_SHARED;
+#endif
+
+
+typedef struct _SGXMKIF_HWDEVICE_SYNC_LIST_
+{
+	IMG_DEV_VIRTADDR	sAccessDevAddr;
+	IMG_UINT32			ui32NumSyncObjects;
+
+	PVRSRV_DEVICE_SYNC_OBJECT	asSyncData[1];
+} SGXMKIF_HWDEVICE_SYNC_LIST, *PSGXMKIF_HWDEVICE_SYNC_LIST;
+
+
+#define PVRSRV_USSE_EDM_INIT_COMPLETE			(1UL << 0)
+
+#define PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE				(1UL << 2)
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE			(1UL << 3)
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE	(1UL << 4)
+#define PVRSRV_USSE_EDM_POWMAN_NO_WORK						(1UL << 5)
+
+#define PVRSRV_USSE_EDM_INTERRUPT_HWR			(1UL << 0)
+#define PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER	(1UL << 1)
+
+#define PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE 	(1UL << 0)
+
+#if defined(FIX_HW_BRN_28889)
+#define PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE 		(1UL << 0)1UL
+#endif
+
+#define PVRSRV_USSE_MISCINFO_READY		0x1UL
+#define PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES	0x2UL
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+#define PVRSRV_USSE_MISCINFO_MEMREAD			0x4UL
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+#define PVRSRV_USSE_MISCINFO_MEMREAD_FAIL		0x1UL << 31
+#endif
+#endif
+
+
+#define	PVRSRV_CLEANUPCMD_RT		0x1
+#define	PVRSRV_CLEANUPCMD_RC		0x2
+#define	PVRSRV_CLEANUPCMD_TC		0x3
+#define	PVRSRV_CLEANUPCMD_2DC		0x4
+#define	PVRSRV_CLEANUPCMD_PB		0x5
+
+#define PVRSRV_POWERCMD_POWEROFF	0x1
+#define PVRSRV_POWERCMD_IDLE		0x2
+#define PVRSRV_POWERCMD_RESUME		0x3
+
+
+#if defined(SGX_FEATURE_BIF_NUM_DIRLISTS)
+#define SGX_BIF_DIR_LIST_INDEX_EDM	(SGX_FEATURE_BIF_NUM_DIRLISTS - 1)
+#else
+#define SGX_BIF_DIR_LIST_INDEX_EDM	(0)
+#endif
+
+#define	SGXMKIF_CC_INVAL_BIF_PT	0x1
+#define	SGXMKIF_CC_INVAL_BIF_PD	0x2
+#define SGXMKIF_CC_INVAL_BIF_SL	0x4
+#define SGXMKIF_CC_INVAL_DATA	0x8
+
+
+
+typedef struct _SGX_MISCINFO_STRUCT_SIZES_
+{
+#if defined (SGX_FEATURE_2D_HARDWARE)
+	IMG_UINT32	ui32Sizeof_2DCMD;
+	IMG_UINT32	ui32Sizeof_2DCMD_SHARED;
+#endif
+	IMG_UINT32	ui32Sizeof_CMDTA;
+	IMG_UINT32	ui32Sizeof_CMDTA_SHARED;
+	IMG_UINT32	ui32Sizeof_TRANSFERCMD;
+	IMG_UINT32	ui32Sizeof_TRANSFERCMD_SHARED;
+	IMG_UINT32	ui32Sizeof_3DREGISTERS;
+	IMG_UINT32	ui32Sizeof_HWPBDESC;
+	IMG_UINT32	ui32Sizeof_HWRENDERCONTEXT;
+	IMG_UINT32	ui32Sizeof_HWRENDERDETAILS;
+	IMG_UINT32	ui32Sizeof_HWRTDATA;
+	IMG_UINT32	ui32Sizeof_HWRTDATASET;
+	IMG_UINT32	ui32Sizeof_HWTRANSFERCONTEXT;
+	IMG_UINT32	ui32Sizeof_HOST_CTL;
+	IMG_UINT32	ui32Sizeof_COMMAND;
+} SGX_MISCINFO_STRUCT_SIZES;
+
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+typedef struct _PVRSRV_SGX_MISCINFO_MEMREAD
+{
+	IMG_DEV_VIRTADDR	sDevVAddr;
+	IMG_DEV_PHYADDR		sPDDevPAddr;
+} PVRSRV_SGX_MISCINFO_MEMREAD;
+#endif
+
+typedef struct _PVRSRV_SGX_MISCINFO_INFO
+{
+	IMG_UINT32						ui32MiscInfoFlags;
+	PVRSRV_SGX_MISCINFO_FEATURES	sSGXFeatures;
+	SGX_MISCINFO_STRUCT_SIZES		sSGXStructSizes;
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+	PVRSRV_SGX_MISCINFO_MEMREAD		sSGXMemReadData;
+#endif
+} PVRSRV_SGX_MISCINFO_INFO;
+
+#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
+#define SGXMK_TRACE_BUFFER_SIZE 512
+#endif
+
+#define SGXMKIF_HWPERF_CB_SIZE					0x100
+
+#if defined(SUPPORT_SGX_HWPERF)
+typedef struct _SGXMKIF_HWPERF_CB_ENTRY_
+{
+	IMG_UINT32	ui32FrameNo;
+	IMG_UINT32	ui32Type;
+	IMG_UINT32	ui32Ordinal;
+	IMG_UINT32	ui32TimeWraps;
+	IMG_UINT32	ui32Time;
+	IMG_UINT32	ui32Counters[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+} SGXMKIF_HWPERF_CB_ENTRY;
+
+typedef struct _SGXMKIF_HWPERF_CB_
+{
+	IMG_UINT32				ui32Woff;
+	IMG_UINT32				ui32Roff;
+	IMG_UINT32				ui32OrdinalGRAPHICS;
+	IMG_UINT32				ui32OrdinalMK_EXECUTION;
+	SGXMKIF_HWPERF_CB_ENTRY psHWPerfCBData[SGXMKIF_HWPERF_CB_SIZE];
+} SGXMKIF_HWPERF_CB;
+#endif
+
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/include/sgxinfo.h b/drivers/gpu/drm/emgd/pvr/services4/include/sgxinfo.h
new file mode 100644
index 0000000..2e85b61
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/include/sgxinfo.h
@@ -0,0 +1,288 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined (__SGXINFO_H__)
+#define __SGXINFO_H__
+
+#include "sgxscript.h"
+#include "servicesint.h"
+#include "services.h"
+#include "sgxapi_km.h"
+#include "sgx_mkif_km.h"
+
+
+#define SGX_MAX_DEV_DATA			24
+#define	SGX_MAX_INIT_MEM_HANDLES	16
+
+
+typedef struct _SGX_BRIDGE_INFO_FOR_SRVINIT
+{
+	IMG_DEV_PHYADDR sPDDevPAddr;
+	PVRSRV_HEAP_INFO asHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+} SGX_BRIDGE_INFO_FOR_SRVINIT;
+
+
+typedef enum _SGXMKIF_CMD_TYPE_
+{
+	SGXMKIF_CMD_TA				= 0,
+	SGXMKIF_CMD_TRANSFER		= 1,
+	SGXMKIF_CMD_2D				= 2,
+	SGXMKIF_CMD_POWER			= 3,
+	SGXMKIF_CMD_CLEANUP			= 4,
+	SGXMKIF_CMD_GETMISCINFO		= 5,
+	SGXMKIF_CMD_PROCESS_QUEUES	= 6,
+	SGXMKIF_CMD_MAX				= 7,
+
+	SGXMKIF_CMD_FORCE_I32   	= -1,
+
+} SGXMKIF_CMD_TYPE;
+
+
+typedef struct _SGX_BRIDGE_INIT_INFO_
+{
+	IMG_HANDLE	hKernelCCBMemInfo;
+	IMG_HANDLE	hKernelCCBCtlMemInfo;
+	IMG_HANDLE	hKernelCCBEventKickerMemInfo;
+	IMG_HANDLE	hKernelSGXHostCtlMemInfo;
+	IMG_HANDLE	hKernelSGXTA3DCtlMemInfo;
+	IMG_HANDLE	hKernelSGXMiscMemInfo;
+
+	IMG_UINT32	aui32HostKickAddr[SGXMKIF_CMD_MAX];
+
+	SGX_INIT_SCRIPTS sScripts;
+
+	IMG_UINT32	ui32ClientBuildOptions;
+	SGX_MISCINFO_STRUCT_SIZES	sSGXStructSizes;
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+	IMG_HANDLE	hKernelHWProfilingMemInfo;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+	IMG_HANDLE	hKernelHWPerfCBMemInfo;
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+	IMG_HANDLE	hKernelEDMStatusBufferMemInfo;
+#endif
+#if defined(SGX_FEATURE_OVERLAPPED_SPM)
+	IMG_HANDLE hKernelTmpRgnHeaderMemInfo;
+#endif
+#if defined(SGX_FEATURE_SPM_MODE_0)
+	IMG_HANDLE hKernelTmpDPMStateMemInfo;
+#endif
+
+	IMG_UINT32 ui32EDMTaskReg0;
+	IMG_UINT32 ui32EDMTaskReg1;
+
+	IMG_UINT32 ui32ClkGateStatusReg;
+	IMG_UINT32 ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+	IMG_UINT32 ui32MasterClkGateStatusReg;
+	IMG_UINT32 ui32MasterClkGateStatusMask;
+#endif
+
+	IMG_UINT32 ui32CacheControl;
+
+	IMG_UINT32	asInitDevData[SGX_MAX_DEV_DATA];
+	IMG_HANDLE	asInitMemHandles[SGX_MAX_INIT_MEM_HANDLES];
+
+} SGX_BRIDGE_INIT_INFO;
+
+
+typedef struct _SGX_DEVICE_SYNC_LIST_
+{
+	PSGXMKIF_HWDEVICE_SYNC_LIST	psHWDeviceSyncList;
+
+	IMG_HANDLE				hKernelHWSyncListMemInfo;
+	PVRSRV_CLIENT_MEM_INFO	*psHWDeviceSyncListClientMemInfo;
+	PVRSRV_CLIENT_MEM_INFO	*psAccessResourceClientMemInfo;
+
+	volatile IMG_UINT32		*pui32Lock;
+
+	struct _SGX_DEVICE_SYNC_LIST_	*psNext;
+
+
+	IMG_UINT32			ui32NumSyncObjects;
+	IMG_HANDLE			ahSyncHandles[1];
+} SGX_DEVICE_SYNC_LIST, *PSGX_DEVICE_SYNC_LIST;
+
+
+typedef struct _SGX_INTERNEL_STATUS_UPDATE_
+{
+	CTL_STATUS				sCtlStatus;
+	IMG_HANDLE				hKernelMemInfo;
+
+	IMG_UINT32				ui32LastStatusUpdateDumpVal;
+} SGX_INTERNEL_STATUS_UPDATE;
+
+
+typedef struct _SGX_CCB_KICK_
+{
+	SGXMKIF_COMMAND		sCommand;
+	IMG_HANDLE			hCCBKernelMemInfo;
+
+	IMG_UINT32	ui32NumDstSyncObjects;
+	IMG_HANDLE	hKernelHWSyncListMemInfo;
+
+
+	IMG_HANDLE	*pahDstSyncHandles;
+
+	IMG_UINT32	ui32NumTAStatusVals;
+	IMG_UINT32	ui32Num3DStatusVals;
+
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+	SGX_INTERNEL_STATUS_UPDATE	asTAStatusUpdate[SGX_MAX_TA_STATUS_VALS];
+	SGX_INTERNEL_STATUS_UPDATE	as3DStatusUpdate[SGX_MAX_3D_STATUS_VALS];
+#else
+	IMG_HANDLE	ahTAStatusSyncInfo[SGX_MAX_TA_STATUS_VALS];
+	IMG_HANDLE	ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS];
+#endif
+
+	IMG_BOOL	bFirstKickOrResume;
+#if (defined(NO_HARDWARE) || defined(PDUMP))
+	IMG_BOOL	bTerminateOrAbort;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+	IMG_BOOL			bKickRender;
+#endif
+
+
+	IMG_UINT32	ui32CCBOffset;
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+	IMG_UINT32	ui32NumTASrcSyncs;
+	IMG_HANDLE	ahTASrcKernelSyncInfo[SGX_MAX_TA_SRC_SYNCS];
+	IMG_UINT32	ui32NumTADstSyncs;
+	IMG_HANDLE	ahTADstKernelSyncInfo[SGX_MAX_TA_DST_SYNCS];
+	IMG_UINT32	ui32Num3DSrcSyncs;
+	IMG_HANDLE	ah3DSrcKernelSyncInfo[SGX_MAX_3D_SRC_SYNCS];
+#else
+
+	IMG_UINT32	ui32NumSrcSyncs;
+	IMG_HANDLE	ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS];
+#endif
+
+
+	IMG_BOOL	bTADependency;
+	IMG_HANDLE	hTA3DSyncInfo;
+
+	IMG_HANDLE	hTASyncInfo;
+	IMG_HANDLE	h3DSyncInfo;
+#if defined(PDUMP)
+	IMG_UINT32	ui32CCBDumpWOff;
+#endif
+#if defined(NO_HARDWARE)
+	IMG_UINT32	ui32WriteOpsPendingVal;
+#endif
+} SGX_CCB_KICK;
+
+
+#define SGX_KERNEL_USE_CODE_BASE_INDEX		15
+
+
+typedef struct _SGX_CLIENT_INFO_
+{
+	IMG_UINT32					ui32ProcessID;
+	IMG_VOID					*pvProcess;
+	PVRSRV_MISC_INFO			sMiscInfo;
+
+	IMG_UINT32					asDevData[SGX_MAX_DEV_DATA];
+
+} SGX_CLIENT_INFO;
+
+typedef struct _SGX_INTERNAL_DEVINFO_
+{
+	IMG_UINT32			ui32Flags;
+	IMG_HANDLE			hHostCtlKernelMemInfoHandle;
+	IMG_BOOL			bForcePTOff;
+} SGX_INTERNAL_DEVINFO;
+
+
+#if defined(TRANSFER_QUEUE)
+typedef struct _PVRSRV_TRANSFER_SGX_KICK_
+{
+	IMG_HANDLE		hCCBMemInfo;
+	IMG_UINT32		ui32SharedCmdCCBOffset;
+
+	IMG_DEV_VIRTADDR 	sHWTransferContextDevVAddr;
+
+	IMG_HANDLE		hTASyncInfo;
+	IMG_HANDLE		h3DSyncInfo;
+
+	IMG_UINT32		ui32NumSrcSync;
+	IMG_HANDLE		ahSrcSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+
+	IMG_UINT32		ui32NumDstSync;
+	IMG_HANDLE		ahDstSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+
+	IMG_UINT32		ui32Flags;
+
+	IMG_UINT32		ui32PDumpFlags;
+#if defined(PDUMP)
+	IMG_UINT32		ui32CCBDumpWOff;
+#endif
+
+	IMG_HANDLE		display;
+	IMG_UINT32		headline;
+	IMG_UINT32		footline;
+} PVRSRV_TRANSFER_SGX_KICK, *PPVRSRV_TRANSFER_SGX_KICK;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _PVRSRV_2D_SGX_KICK_
+{
+	IMG_HANDLE		hCCBMemInfo;
+	IMG_UINT32		ui32SharedCmdCCBOffset;
+
+	IMG_DEV_VIRTADDR 	sHW2DContextDevVAddr;
+
+	IMG_UINT32		ui32NumSrcSync;
+	IMG_HANDLE		ahSrcSyncInfo[SGX_MAX_2D_SRC_SYNC_OPS];
+
+
+	IMG_HANDLE 		hDstSyncInfo;
+
+
+	IMG_HANDLE		hTASyncInfo;
+
+
+	IMG_HANDLE		h3DSyncInfo;
+
+	IMG_UINT32		ui32PDumpFlags;
+#if defined(PDUMP)
+	IMG_UINT32		ui32CCBDumpWOff;
+#endif
+} PVRSRV_2D_SGX_KICK, *PPVRSRV_2D_SGX_KICK;
+#endif
+#endif
+
+#define PVRSRV_SGX_DIFF_NUM_COUNTERS	9
+
+typedef struct _PVRSRV_SGXDEV_DIFF_INFO_
+{
+	IMG_UINT32	aui32Counters[PVRSRV_SGX_DIFF_NUM_COUNTERS];
+	IMG_UINT32	ui32Time[3];
+	IMG_UINT32	ui32Marker[2];
+} PVRSRV_SGXDEV_DIFF_INFO, *PPVRSRV_SGXDEV_DIFF_INFO;
+
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_pvr_bridge.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_pvr_bridge.c
new file mode 100644
index 0000000..efabffe
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_pvr_bridge.c
@@ -0,0 +1,3447 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+
+
+#include <stddef.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "pvr_bridge_km.h"
+#include "pvr_debug.h"
+#include "ra.h"
+#include "pvr_bridge.h"
+#if defined(SUPPORT_SGX)
+#include "sgx_bridge.h"
+#endif
+#if defined(SUPPORT_VGX)
+#include "vgx_bridge.h"
+#endif
+#if defined(SUPPORT_MSVDX)
+#include "msvdx_bridge.h"
+#endif
+#include "perproc.h"
+#include "device.h"
+#include "buffer_manager.h"
+
+#include "pdump_km.h"
+#include "sysconfig.h"
+
+#include "bridged_pvr_bridge.h"
+#if defined(SUPPORT_SGX)
+#include "bridged_sgx_bridge.h"
+#endif
+#if defined(SUPPORT_VGX)
+#include "bridged_vgx_bridge.h"
+#endif
+#if defined(SUPPORT_MSVDX)
+#include "bridged_msvdx_bridge.h"
+#endif
+
+#include "env_data.h"
+
+#if defined (__linux__)
+#include "mmap.h"
+#endif
+
+#include "srvkm.h"
+
+PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+#if defined(PVR_SECURE_HANDLES)
+static IMG_BOOL abSharedDeviceMemHeap[PVRSRV_MAX_CLIENT_HEAPS];
+static IMG_BOOL *pbSharedDeviceMemHeap = abSharedDeviceMemHeap;
+#else
+static IMG_BOOL *pbSharedDeviceMemHeap = (IMG_BOOL*)IMG_NULL;
+#endif
+
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_ERROR
+CopyFromUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+					IMG_UINT32 ui32BridgeID,
+					IMG_VOID *pvDest,
+					IMG_VOID *pvSrc,
+					IMG_UINT32 ui32Size)
+{
+	g_BridgeDispatchTable[ui32BridgeID].ui32CopyFromUserTotalBytes+=ui32Size;
+	g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+=ui32Size;
+	return OSCopyFromUser(pProcData, pvDest, pvSrc, ui32Size);
+}
+PVRSRV_ERROR
+CopyToUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+				  IMG_UINT32 ui32BridgeID,
+				  IMG_VOID *pvDest,
+				  IMG_VOID *pvSrc,
+				  IMG_UINT32 ui32Size)
+{
+	g_BridgeDispatchTable[ui32BridgeID].ui32CopyToUserTotalBytes+=ui32Size;
+	g_BridgeGlobalStats.ui32TotalCopyToUserBytes+=ui32Size;
+	return OSCopyToUser(pProcData, pvDest, pvSrc, ui32Size);
+}
+#endif
+
+
+static IMG_INT
+PVRSRVEnumerateDevicesBW(IMG_UINT32 ui32BridgeID,
+						 IMG_VOID *psBridgeIn,
+						 PVRSRV_BRIDGE_OUT_ENUMDEVICE *psEnumDeviceOUT,
+						 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DEVICES);
+
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+	psEnumDeviceOUT->eError =
+		PVRSRVEnumerateDevicesKM(&psEnumDeviceOUT->ui32NumDevices,
+								 psEnumDeviceOUT->asDeviceIdentifier);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVAcquireDeviceDataBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO *psAcquireDevInfoIN,
+						  PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO *psAcquireDevInfoOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO);
+
+	psAcquireDevInfoOUT->eError =
+		PVRSRVAcquireDeviceDataKM(psAcquireDevInfoIN->uiDevIndex,
+								  psAcquireDevInfoIN->eDeviceType,
+								  &hDevCookieInt);
+	if(psAcquireDevInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+		psAcquireDevInfoOUT->eError =
+		PVRSRVAllocHandle(psPerProc->psHandleBase,
+						  &psAcquireDevInfoOUT->hDevCookie,
+						  hDevCookieInt,
+						  PVRSRV_HANDLE_TYPE_DEV_NODE,
+						  PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVCreateDeviceMemContextBW(IMG_UINT32 ui32BridgeID,
+							   PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT *psCreateDevMemContextIN,
+							   PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT *psCreateDevMemContextOUT,
+							   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hDevMemContextInt;
+	IMG_UINT32 i;
+	IMG_BOOL bCreated;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT);
+
+
+	NEW_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS + 1);
+
+	psCreateDevMemContextOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psCreateDevMemContextIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psCreateDevMemContextOUT->eError =
+		PVRSRVCreateDeviceMemContextKM(hDevCookieInt,
+									   psPerProc,
+									   &hDevMemContextInt,
+									   &psCreateDevMemContextOUT->ui32ClientHeapCount,
+									   &psCreateDevMemContextOUT->sHeapInfo[0],
+									   &bCreated,
+									   pbSharedDeviceMemHeap);
+
+	if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+	if(bCreated)
+	{
+		PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+						  &psCreateDevMemContextOUT->hDevMemContext,
+						  hDevMemContextInt,
+						  PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT,
+						  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+	}
+	else
+	{
+		psCreateDevMemContextOUT->eError =
+			PVRSRVFindHandle(psPerProc->psHandleBase,
+							 &psCreateDevMemContextOUT->hDevMemContext,
+							 hDevMemContextInt,
+							 PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+		if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	for(i = 0; i < psCreateDevMemContextOUT->ui32ClientHeapCount; i++)
+	{
+		IMG_HANDLE hDevMemHeapExt;
+
+#if defined(PVR_SECURE_HANDLES)
+		if(abSharedDeviceMemHeap[i])
+#endif
+		{
+
+			PVRSRVAllocHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+							  psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+							  PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+							  PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+		}
+#if defined(PVR_SECURE_HANDLES)
+		else
+		{
+
+			if(bCreated)
+			{
+				PVRSRVAllocSubHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+									 psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+									 PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+									 PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+									 psCreateDevMemContextOUT->hDevMemContext);
+			}
+			else
+			{
+				psCreateDevMemContextOUT->eError =
+					PVRSRVFindHandle(psPerProc->psHandleBase, &hDevMemHeapExt,
+									 psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+									 PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+				if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+				{
+					return 0;
+				}
+			}
+		}
+#endif
+		psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap = hDevMemHeapExt;
+	}
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError, psPerProc);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVDestroyDeviceMemContextBW(IMG_UINT32 ui32BridgeID,
+								PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT *psDestroyDevMemContextIN,
+								PVRSRV_BRIDGE_RETURN *psRetOUT,
+								PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hDevMemContextInt;
+	IMG_BOOL bDestroyed;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psDestroyDevMemContextIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+						   psDestroyDevMemContextIN->hDevMemContext,
+						   PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVDestroyDeviceMemContextKM(hDevCookieInt, hDevMemContextInt, &bDestroyed);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	if(bDestroyed)
+	{
+		psRetOUT->eError =
+			PVRSRVReleaseHandle(psPerProc->psHandleBase,
+								psDestroyDevMemContextIN->hDevMemContext,
+								PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+	}
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVGetDeviceMemHeapInfoBW(IMG_UINT32 ui32BridgeID,
+							   PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO *psGetDevMemHeapInfoIN,
+							   PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO *psGetDevMemHeapInfoOUT,
+							   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hDevMemContextInt;
+	IMG_UINT32 i;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psGetDevMemHeapInfoOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS);
+
+	psGetDevMemHeapInfoOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psGetDevMemHeapInfoIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetDevMemHeapInfoOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+						   psGetDevMemHeapInfoIN->hDevMemContext,
+						   PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+	if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetDevMemHeapInfoOUT->eError =
+		PVRSRVGetDeviceMemHeapInfoKM(hDevCookieInt,
+									   hDevMemContextInt,
+									   &psGetDevMemHeapInfoOUT->ui32ClientHeapCount,
+									   &psGetDevMemHeapInfoOUT->sHeapInfo[0],
+									   pbSharedDeviceMemHeap);
+
+	if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	for(i = 0; i < psGetDevMemHeapInfoOUT->ui32ClientHeapCount; i++)
+	{
+		IMG_HANDLE hDevMemHeapExt;
+
+#if defined(PVR_SECURE_HANDLES)
+		if(abSharedDeviceMemHeap[i])
+#endif
+		{
+
+			PVRSRVAllocHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+							  psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap,
+							  PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+							  PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+		}
+#if defined(PVR_SECURE_HANDLES)
+		else
+		{
+
+			psGetDevMemHeapInfoOUT->eError =
+				PVRSRVFindHandle(psPerProc->psHandleBase, &hDevMemHeapExt,
+								 psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap,
+								 PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+			if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+			{
+				return 0;
+			}
+		}
+#endif
+		psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap = hDevMemHeapExt;
+	}
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psGetDevMemHeapInfoOUT->eError, psPerProc);
+
+	return 0;
+}
+
+
+#if defined(OS_PVRSRV_ALLOC_DEVICE_MEM_BW)
+IMG_INT
+PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *psAllocDeviceMemIN,
+					   PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM *psAllocDeviceMemOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc);
+#else
+static IMG_INT
+PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *psAllocDeviceMemIN,
+					   PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM *psAllocDeviceMemOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hDevMemHeapInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_DEVICEMEM);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc, 2);
+
+	psAllocDeviceMemOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psAllocDeviceMemIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psAllocDeviceMemOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemHeapInt,
+						   psAllocDeviceMemIN->hDevMemHeap,
+						   PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+
+	if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psAllocDeviceMemOUT->eError =
+		PVRSRVAllocDeviceMemKM(hDevCookieInt,
+							   psPerProc,
+							   hDevMemHeapInt,
+							   psAllocDeviceMemIN->ui32Attribs,
+							   psAllocDeviceMemIN->ui32Size,
+							   psAllocDeviceMemIN->ui32Alignment,
+							   &psMemInfo,
+							   "" );
+
+	if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	OSMemSet(&psAllocDeviceMemOUT->sClientMemInfo,
+			 0,
+			 sizeof(psAllocDeviceMemOUT->sClientMemInfo));
+
+	psAllocDeviceMemOUT->sClientMemInfo.pvLinAddrKM =
+			psMemInfo->pvLinAddrKM;
+
+#if defined (__linux__)
+	psAllocDeviceMemOUT->sClientMemInfo.pvLinAddr = 0;
+#else
+	psAllocDeviceMemOUT->sClientMemInfo.pvLinAddr = psMemInfo->pvLinAddrKM;
+#endif
+	psAllocDeviceMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+	psAllocDeviceMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+	psAllocDeviceMemOUT->sClientMemInfo.ui32AllocSize = psMemInfo->ui32AllocSize;
+	psAllocDeviceMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psAllocDeviceMemOUT->sClientMemInfo.hKernelMemInfo,
+					  psMemInfo,
+					  PVRSRV_HANDLE_TYPE_MEM_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+	if(psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_NO_SYNCOBJ)
+	{
+
+		OSMemSet(&psAllocDeviceMemOUT->sClientSyncInfo,
+				 0,
+				 sizeof (PVRSRV_CLIENT_SYNC_INFO));
+		psAllocDeviceMemOUT->sClientMemInfo.psClientSyncInfo = IMG_NULL;
+		psAllocDeviceMemOUT->psKernelSyncInfo = IMG_NULL;
+	}
+	else
+	{
+
+		psAllocDeviceMemOUT->psKernelSyncInfo = psMemInfo->psKernelSyncInfo;
+
+		psAllocDeviceMemOUT->sClientSyncInfo.psSyncData =
+			psMemInfo->psKernelSyncInfo->psSyncData;
+		psAllocDeviceMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+			psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+		psAllocDeviceMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+			psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+		psAllocDeviceMemOUT->sClientSyncInfo.hMappingInfo =
+			psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+		PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+							 &psAllocDeviceMemOUT->sClientSyncInfo.hKernelSyncInfo,
+							 psMemInfo->psKernelSyncInfo,
+							 PVRSRV_HANDLE_TYPE_SYNC_INFO,
+							 PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+							 psAllocDeviceMemOUT->sClientMemInfo.hKernelMemInfo);
+
+		psAllocDeviceMemOUT->sClientMemInfo.psClientSyncInfo =
+			&psAllocDeviceMemOUT->sClientSyncInfo;
+
+	}
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc);
+
+	return 0;
+}
+
+#endif
+
+static IMG_INT
+PVRSRVFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_FREEDEVICEMEM *psFreeDeviceMemIN,
+					  PVRSRV_BRIDGE_RETURN *psRetOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_VOID *pvKernelMemInfo;
+
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_DEVICEMEM);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psFreeDeviceMemIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &pvKernelMemInfo,
+						   psFreeDeviceMemIN->psKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = PVRSRVFreeDeviceMemKM(hDevCookieInt, pvKernelMemInfo);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psFreeDeviceMemIN->psKernelMemInfo,
+							PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVExportDeviceMemBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM *psExportDeviceMemIN,
+					  PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EXPORT_DEVICEMEM);
+
+
+	psExportDeviceMemOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psExportDeviceMemIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psExportDeviceMemOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: can't find devcookie"));
+		return 0;
+	}
+
+
+	psExportDeviceMemOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_PVOID *)&psKernelMemInfo,
+						   psExportDeviceMemIN->psKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	if(psExportDeviceMemOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: can't find kernel meminfo"));
+		return 0;
+	}
+
+
+	psExportDeviceMemOUT->eError =
+		PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+							 &psExportDeviceMemOUT->hMemInfo,
+							 psKernelMemInfo,
+							 PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psExportDeviceMemOUT->eError == PVRSRV_OK)
+	{
+
+		PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVExportDeviceMemBW: allocation is already exported"));
+		return 0;
+	}
+
+
+	psExportDeviceMemOUT->eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+													&psExportDeviceMemOUT->hMemInfo,
+													psKernelMemInfo,
+													PVRSRV_HANDLE_TYPE_MEM_INFO,
+													PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+	if (psExportDeviceMemOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: failed to allocate handle from global handle list"));
+		return 0;
+	}
+
+
+	psKernelMemInfo->ui32Flags |= PVRSRV_MEM_EXPORTED;
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
+							 PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN,
+							 PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDevMemOUT,
+							 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_KERNEL_MEM_INFO	*psSrcKernelMemInfo = IMG_NULL;
+	PVRSRV_KERNEL_MEM_INFO	*psDstKernelMemInfo = IMG_NULL;
+	IMG_HANDLE				hDstDevMemHeap = IMG_NULL;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_DEV_MEMORY);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psMapDevMemOUT->eError, psPerProc, 2);
+
+
+	psMapDevMemOUT->eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+												(IMG_VOID**)&psSrcKernelMemInfo,
+												psMapDevMemIN->hKernelMemInfo,
+												PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psMapDevMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+	psMapDevMemOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+												&hDstDevMemHeap,
+												psMapDevMemIN->hDstDevMemHeap,
+												PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+	if(psMapDevMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+	psMapDevMemOUT->eError = PVRSRVMapDeviceMemoryKM(psPerProc,
+												  psSrcKernelMemInfo,
+												  hDstDevMemHeap,
+												  &psDstKernelMemInfo);
+	if(psMapDevMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	OSMemSet(&psMapDevMemOUT->sDstClientMemInfo,
+			 0,
+			 sizeof(psMapDevMemOUT->sDstClientMemInfo));
+	OSMemSet(&psMapDevMemOUT->sDstClientSyncInfo,
+			 0,
+			 sizeof(psMapDevMemOUT->sDstClientSyncInfo));
+
+	psMapDevMemOUT->sDstClientMemInfo.pvLinAddrKM =
+			psDstKernelMemInfo->pvLinAddrKM;
+
+	psMapDevMemOUT->sDstClientMemInfo.pvLinAddr = 0;
+	psMapDevMemOUT->sDstClientMemInfo.sDevVAddr = psDstKernelMemInfo->sDevVAddr;
+	psMapDevMemOUT->sDstClientMemInfo.ui32Flags = psDstKernelMemInfo->ui32Flags;
+	psMapDevMemOUT->sDstClientMemInfo.ui32AllocSize = psDstKernelMemInfo->ui32AllocSize;
+	psMapDevMemOUT->sDstClientMemInfo.hMappingInfo = psDstKernelMemInfo->sMemBlk.hOSMemHandle;
+
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo,
+					  psDstKernelMemInfo,
+					  PVRSRV_HANDLE_TYPE_MEM_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+	psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo = IMG_NULL;
+	psMapDevMemOUT->psDstKernelSyncInfo = IMG_NULL;
+
+
+	if(psDstKernelMemInfo->psKernelSyncInfo)
+	{
+		psMapDevMemOUT->psDstKernelSyncInfo = psDstKernelMemInfo->psKernelSyncInfo;
+
+		psMapDevMemOUT->sDstClientSyncInfo.psSyncData =
+			psDstKernelMemInfo->psKernelSyncInfo->psSyncData;
+		psMapDevMemOUT->sDstClientSyncInfo.sWriteOpsCompleteDevVAddr =
+			psDstKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+		psMapDevMemOUT->sDstClientSyncInfo.sReadOpsCompleteDevVAddr =
+			psDstKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+		psMapDevMemOUT->sDstClientSyncInfo.hMappingInfo =
+			psDstKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+		psMapDevMemOUT->sDstClientMemInfo.psClientSyncInfo = &psMapDevMemOUT->sDstClientSyncInfo;
+
+		PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+					  &psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo,
+					  psDstKernelMemInfo->psKernelSyncInfo,
+					  PVRSRV_HANDLE_TYPE_SYNC_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+					  psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo);
+	}
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psMapDevMemOUT->eError, psPerProc);
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVUnmapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
+							 PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY *psUnmapDevMemIN,
+							 PVRSRV_BRIDGE_RETURN *psRetOUT,
+							 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_KERNEL_MEM_INFO	*psKernelMemInfo = IMG_NULL;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_DEV_MEMORY);
+
+	psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+											(IMG_VOID**)&psKernelMemInfo,
+											psUnmapDevMemIN->psKernelMemInfo,
+											PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = PVRSRVUnmapDeviceMemoryKM(psKernelMemInfo);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psUnmapDevMemIN->psKernelMemInfo,
+							PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	return 0;
+}
+
+
+
+static IMG_INT
+PVRSRVMapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
+							 PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY *psMapDevClassMemIN,
+							 PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psMapDevClassMemOUT,
+							 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+	IMG_HANDLE hOSMapInfo;
+	IMG_HANDLE hDeviceClassBufferInt;
+	IMG_HANDLE hDevMemContextInt;
+	PVRSRV_HANDLE_TYPE eHandleType;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psMapDevClassMemOUT->eError, psPerProc, 2);
+
+
+	psMapDevClassMemOUT->eError =
+		PVRSRVLookupHandleAnyType(psPerProc->psHandleBase, &hDeviceClassBufferInt,
+								  &eHandleType,
+								  psMapDevClassMemIN->hDeviceClassBuffer);
+
+	if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+	psMapDevClassMemOUT->eError =
+	PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+				   psMapDevClassMemIN->hDevMemContext,
+				   PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+	if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+	switch(eHandleType)
+	{
+#if defined(PVR_SECURE_HANDLES)
+		case PVRSRV_HANDLE_TYPE_DISP_BUFFER:
+		case PVRSRV_HANDLE_TYPE_BUF_BUFFER:
+#else
+		case PVRSRV_HANDLE_TYPE_NONE:
+#endif
+			break;
+		default:
+			psMapDevClassMemOUT->eError = PVRSRV_ERROR_GENERIC;
+			return 0;
+	}
+
+	psMapDevClassMemOUT->eError =
+		PVRSRVMapDeviceClassMemoryKM(psPerProc,
+									 hDevMemContextInt,
+									 hDeviceClassBufferInt,
+									 &psMemInfo,
+									 &hOSMapInfo);
+	if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	OSMemSet(&psMapDevClassMemOUT->sClientMemInfo,
+			 0,
+			 sizeof(psMapDevClassMemOUT->sClientMemInfo));
+	OSMemSet(&psMapDevClassMemOUT->sClientSyncInfo,
+			 0,
+			 sizeof(psMapDevClassMemOUT->sClientSyncInfo));
+
+	psMapDevClassMemOUT->sClientMemInfo.pvLinAddrKM =
+			psMemInfo->pvLinAddrKM;
+
+	psMapDevClassMemOUT->sClientMemInfo.pvLinAddr = 0;
+	psMapDevClassMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+	psMapDevClassMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+	psMapDevClassMemOUT->sClientMemInfo.ui32AllocSize = psMemInfo->ui32AllocSize;
+	psMapDevClassMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+	psMapDevClassMemOUT->sClientMemInfo.hOSMapInfo = hOSMapInfo;
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+					  &psMapDevClassMemOUT->sClientMemInfo.hKernelMemInfo,
+					  psMemInfo,
+					  PVRSRV_HANDLE_TYPE_MEM_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+					  psMapDevClassMemIN->hDeviceClassBuffer);
+
+	psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo = IMG_NULL;
+	psMapDevClassMemOUT->psKernelSyncInfo = IMG_NULL;
+
+
+	if(psMemInfo->psKernelSyncInfo)
+	{
+		psMapDevClassMemOUT->psKernelSyncInfo = psMemInfo->psKernelSyncInfo;
+
+		psMapDevClassMemOUT->sClientSyncInfo.psSyncData =
+			psMemInfo->psKernelSyncInfo->psSyncData;
+		psMapDevClassMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+			psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+		psMapDevClassMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+			psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+		psMapDevClassMemOUT->sClientSyncInfo.hMappingInfo =
+			psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+		psMapDevClassMemOUT->sClientMemInfo.psClientSyncInfo = &psMapDevClassMemOUT->sClientSyncInfo;
+
+		PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+						  &psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo,
+						  psMemInfo->psKernelSyncInfo,
+						  PVRSRV_HANDLE_TYPE_SYNC_INFO,
+						  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+						  psMapDevClassMemOUT->sClientMemInfo.hKernelMemInfo);
+	}
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psMapDevClassMemOUT->eError, psPerProc);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVUnmapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
+							   PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY *psUnmapDevClassMemIN,
+							   PVRSRV_BRIDGE_RETURN *psRetOUT,
+							   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvKernelMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &pvKernelMemInfo,
+						   psUnmapDevClassMemIN->psKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = PVRSRVUnmapDeviceClassMemoryKM(pvKernelMemInfo);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psUnmapDevClassMemIN->psKernelMemInfo,
+							PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	return 0;
+}
+
+
+#if defined(OS_PVRSRV_WRAP_EXT_MEM_BW)
+IMG_INT
+PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
+					  PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY *psWrapExtMemOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc);
+#else
+static IMG_INT
+PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
+					  PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY *psWrapExtMemOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hDevMemContextInt;
+	PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+	IMG_UINT32 ui32PageTableSize = 0;
+	IMG_SYS_PHYADDR *psSysPAddr = IMG_NULL;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_WRAP_EXT_MEMORY);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc, 2);
+
+
+	psWrapExtMemOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psWrapExtMemIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psWrapExtMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+	psWrapExtMemOUT->eError =
+	PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+				   psWrapExtMemIN->hDevMemContext,
+				   PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+	if(psWrapExtMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	if(psWrapExtMemIN->ui32NumPageTableEntries)
+	{
+		ui32PageTableSize = psWrapExtMemIN->ui32NumPageTableEntries
+						* sizeof(IMG_SYS_PHYADDR);
+
+		ASSIGN_AND_EXIT_ON_ERROR(psWrapExtMemOUT->eError,
+				  OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  ui32PageTableSize,
+				  (IMG_VOID **)&psSysPAddr, 0,
+				  "Page Table"));
+
+		if(CopyFromUserWrapper(psPerProc,
+							   ui32BridgeID,
+							   psSysPAddr,
+							   psWrapExtMemIN->psSysPAddr,
+							   ui32PageTableSize) != PVRSRV_OK)
+		{
+			OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 	ui32PageTableSize, (IMG_VOID *)psSysPAddr, 0);
+
+			return -EFAULT;
+		}
+	}
+
+	psWrapExtMemOUT->eError =
+		PVRSRVWrapExtMemoryKM(hDevCookieInt,
+							  psPerProc,
+							  hDevMemContextInt,
+							  psWrapExtMemIN->ui32ByteSize,
+							  psWrapExtMemIN->ui32PageOffset,
+							  psWrapExtMemIN->bPhysContig,
+							  psSysPAddr,
+							  psWrapExtMemIN->pvLinAddr,
+							  psWrapExtMemIN->ui32Flags,
+							  &psMemInfo);
+	if(psWrapExtMemIN->ui32NumPageTableEntries)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+			  ui32PageTableSize,
+			  (IMG_VOID *)psSysPAddr, 0);
+
+	}
+	if(psWrapExtMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psWrapExtMemOUT->sClientMemInfo.pvLinAddrKM =
+			psMemInfo->pvLinAddrKM;
+
+
+	psWrapExtMemOUT->sClientMemInfo.pvLinAddr = 0;
+	psWrapExtMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+	psWrapExtMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+	psWrapExtMemOUT->sClientMemInfo.ui32AllocSize = psMemInfo->ui32AllocSize;
+	psWrapExtMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo,
+					  psMemInfo,
+					  PVRSRV_HANDLE_TYPE_MEM_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+
+	psWrapExtMemOUT->sClientSyncInfo.psSyncData =
+		psMemInfo->psKernelSyncInfo->psSyncData;
+	psWrapExtMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+		psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+	psWrapExtMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+		psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+	psWrapExtMemOUT->sClientSyncInfo.hMappingInfo =
+		psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+	psWrapExtMemOUT->sClientMemInfo.psClientSyncInfo = &psWrapExtMemOUT->sClientSyncInfo;
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+					  &psWrapExtMemOUT->sClientSyncInfo.hKernelSyncInfo,
+					  (IMG_HANDLE)psMemInfo->psKernelSyncInfo,
+					  PVRSRV_HANDLE_TYPE_SYNC_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+					  psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc);
+
+	return 0;
+}
+#endif
+
+static IMG_INT
+PVRSRVUnwrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+						PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY *psUnwrapExtMemIN,
+						PVRSRV_BRIDGE_RETURN *psRetOUT,
+						PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvMemInfo,
+						   psUnwrapExtMemIN->hKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVUnwrapExtMemoryKM((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+						   psUnwrapExtMemIN->hKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVGetFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
+						 PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM *psGetFreeDeviceMemIN,
+						 PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM *psGetFreeDeviceMemOUT,
+						 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GETFREE_DEVICEMEM);
+
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	psGetFreeDeviceMemOUT->eError =
+		PVRSRVGetFreeDeviceMemKM(psGetFreeDeviceMemIN->ui32Flags,
+								 &psGetFreeDeviceMemOUT->ui32Total,
+								 &psGetFreeDeviceMemOUT->ui32Free,
+								 &psGetFreeDeviceMemOUT->ui32LargestBlock);
+
+	return 0;
+}
+
+static IMG_INT
+PVRMMapOSMemHandleToMMapDataBW(IMG_UINT32 ui32BridgeID,
+								  PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA *psMMapDataIN,
+								  PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA *psMMapDataOUT,
+								  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA);
+
+#if defined (__linux__)
+	psMMapDataOUT->eError =
+		PVRMMapOSMemHandleToMMapData(psPerProc,
+										psMMapDataIN->hMHandle,
+										&psMMapDataOUT->ui32MMapOffset,
+										&psMMapDataOUT->ui32ByteOffset,
+										&psMMapDataOUT->ui32RealByteSize,
+										&psMMapDataOUT->ui32UserVAddr);
+#else
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+	PVR_UNREFERENCED_PARAMETER(psMMapDataIN);
+
+	psMMapDataOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+	return 0;
+}
+
+
+static IMG_INT
+PVRMMapReleaseMMapDataBW(IMG_UINT32 ui32BridgeID,
+								  PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA *psMMapDataIN,
+								  PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA *psMMapDataOUT,
+								  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RELEASE_MMAP_DATA);
+
+#if defined (__linux__)
+	psMMapDataOUT->eError =
+		PVRMMapReleaseMMapData(psPerProc,
+										psMMapDataIN->hMHandle,
+										&psMMapDataOUT->bMUnmap,
+										&psMMapDataOUT->ui32RealByteSize,
+										&psMMapDataOUT->ui32UserVAddr);
+#else
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+	PVR_UNREFERENCED_PARAMETER(psMMapDataIN);
+
+	psMMapDataOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+	return 0;
+}
+
+
+#ifdef PDUMP
+static IMG_INT
+PDumpIsCaptureFrameBW(IMG_UINT32 ui32BridgeID,
+					  IMG_VOID *psBridgeIn,
+					  PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING *psPDumpIsCapturingOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_ISCAPTURING);
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	psPDumpIsCapturingOUT->bIsCapturing = PDumpIsCaptureFrameKM();
+	psPDumpIsCapturingOUT->eError = PVRSRV_OK;
+
+	return 0;
+}
+
+static IMG_INT
+PDumpCommentBW(IMG_UINT32 ui32BridgeID,
+			   PVRSRV_BRIDGE_IN_PDUMP_COMMENT *psPDumpCommentIN,
+			   PVRSRV_BRIDGE_RETURN *psRetOUT,
+			   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_COMMENT);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	psRetOUT->eError = PDumpCommentKM(&psPDumpCommentIN->szComment[0],
+									  psPDumpCommentIN->ui32Flags);
+	return 0;
+}
+
+static IMG_INT
+PDumpSetFrameBW(IMG_UINT32 ui32BridgeID,
+				PVRSRV_BRIDGE_IN_PDUMP_SETFRAME *psPDumpSetFrameIN,
+				PVRSRV_BRIDGE_RETURN *psRetOUT,
+				PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_SETFRAME);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	psRetOUT->eError = PDumpSetFrameKM(psPDumpSetFrameIN->ui32Frame);
+
+	return 0;
+}
+
+static IMG_INT
+PDumpRegWithFlagsBW(IMG_UINT32 ui32BridgeID,
+					PVRSRV_BRIDGE_IN_PDUMP_DUMPREG *psPDumpRegDumpIN,
+					PVRSRV_BRIDGE_RETURN *psRetOUT,
+					PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REG);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	psRetOUT->eError =
+		PDumpRegWithFlagsKM(psPDumpRegDumpIN->sHWReg.ui32RegAddr,
+							psPDumpRegDumpIN->sHWReg.ui32RegVal,
+							psPDumpRegDumpIN->ui32Flags);
+
+	return 0;
+}
+
+static IMG_INT
+PDumpRegPolBW(IMG_UINT32 ui32BridgeID,
+			  PVRSRV_BRIDGE_IN_PDUMP_REGPOL *psPDumpRegPolIN,
+			  PVRSRV_BRIDGE_RETURN *psRetOUT,
+			  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REGPOL);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	psRetOUT->eError =
+		PDumpRegPolWithFlagsKM(psPDumpRegPolIN->sHWReg.ui32RegAddr,
+							   psPDumpRegPolIN->sHWReg.ui32RegVal,
+							   psPDumpRegPolIN->ui32Mask,
+							   psPDumpRegPolIN->ui32Flags);
+
+	return 0;
+}
+
+static IMG_INT
+PDumpMemPolBW(IMG_UINT32 ui32BridgeID,
+			  PVRSRV_BRIDGE_IN_PDUMP_MEMPOL *psPDumpMemPolIN,
+			  PVRSRV_BRIDGE_RETURN *psRetOUT,
+			  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_MEMPOL);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvMemInfo,
+						   psPDumpMemPolIN->psKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PDumpMemPolKM(((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo),
+					  psPDumpMemPolIN->ui32Offset,
+					  psPDumpMemPolIN->ui32Value,
+					  psPDumpMemPolIN->ui32Mask,
+					  PDUMP_POLL_OPERATOR_EQUAL,
+					  psPDumpMemPolIN->ui32Flags,
+					  MAKEUNIQUETAG(pvMemInfo));
+
+	return 0;
+}
+
+static IMG_INT
+PDumpMemBW(IMG_UINT32 ui32BridgeID,
+		   PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM *psPDumpMemDumpIN,
+		   PVRSRV_BRIDGE_RETURN *psRetOUT,
+		   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPMEM);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvMemInfo,
+						   psPDumpMemDumpIN->psKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PDumpMemUM(psPerProc,
+				   psPDumpMemDumpIN->pvAltLinAddr,
+				   psPDumpMemDumpIN->pvLinAddr,
+				   pvMemInfo,
+				   psPDumpMemDumpIN->ui32Offset,
+				   psPDumpMemDumpIN->ui32Bytes,
+				   psPDumpMemDumpIN->ui32Flags,
+				   MAKEUNIQUETAG(pvMemInfo));
+
+	return 0;
+}
+
+static IMG_INT
+PDumpBitmapBW(IMG_UINT32 ui32BridgeID,
+			  PVRSRV_BRIDGE_IN_PDUMP_BITMAP *psPDumpBitmapIN,
+			  PVRSRV_BRIDGE_RETURN *psRetOUT,
+			  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+	PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+	psRetOUT->eError =
+		PDumpBitmapKM(&psPDumpBitmapIN->szFileName[0],
+					  psPDumpBitmapIN->ui32FileOffset,
+					  psPDumpBitmapIN->ui32Width,
+					  psPDumpBitmapIN->ui32Height,
+					  psPDumpBitmapIN->ui32StrideInBytes,
+					  psPDumpBitmapIN->sDevBaseAddr,
+					  psPDumpBitmapIN->ui32Size,
+					  psPDumpBitmapIN->ePixelFormat,
+					  psPDumpBitmapIN->eMemFormat,
+					  psPDumpBitmapIN->ui32Flags);
+
+	return 0;
+}
+
+static IMG_INT
+PDumpReadRegBW(IMG_UINT32 ui32BridgeID,
+			   PVRSRV_BRIDGE_IN_PDUMP_READREG *psPDumpReadRegIN,
+			   PVRSRV_BRIDGE_RETURN *psRetOUT,
+			   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPREADREG);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	psRetOUT->eError =
+		PDumpReadRegKM(&psPDumpReadRegIN->szFileName[0],
+					   psPDumpReadRegIN->ui32FileOffset,
+					   psPDumpReadRegIN->ui32Address,
+					   psPDumpReadRegIN->ui32Size,
+					   psPDumpReadRegIN->ui32Flags);
+
+	return 0;
+}
+
+static IMG_INT
+PDumpDriverInfoBW(IMG_UINT32 ui32BridgeID,
+				  PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO *psPDumpDriverInfoIN,
+				  PVRSRV_BRIDGE_RETURN *psRetOUT,
+				  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_UINT32 ui32PDumpFlags;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DRIVERINFO);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	ui32PDumpFlags = 0;
+	if(psPDumpDriverInfoIN->bContinuous)
+	{
+		ui32PDumpFlags |= PDUMP_FLAGS_CONTINUOUS;
+	}
+	psRetOUT->eError =
+		PDumpDriverInfoKM(&psPDumpDriverInfoIN->szString[0],
+						  ui32PDumpFlags);
+
+	return 0;
+}
+
+static IMG_INT
+PDumpSyncDumpBW(IMG_UINT32 ui32BridgeID,
+				PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC *psPDumpSyncDumpIN,
+				PVRSRV_BRIDGE_RETURN *psRetOUT,
+				PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_UINT32 ui32Bytes = psPDumpSyncDumpIN->ui32Bytes;
+	IMG_VOID *pvSyncInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPSYNC);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+						   psPDumpSyncDumpIN->psKernelSyncInfo,
+						   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PDumpMemUM(psPerProc,
+				   psPDumpSyncDumpIN->pvAltLinAddr,
+				   IMG_NULL,
+				   ((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM,
+				   psPDumpSyncDumpIN->ui32Offset,
+				   ui32Bytes,
+				   0,
+				   MAKEUNIQUETAG(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM));
+
+	return 0;
+}
+
+static IMG_INT
+PDumpSyncPolBW(IMG_UINT32 ui32BridgeID,
+			   PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL *psPDumpSyncPolIN,
+			   PVRSRV_BRIDGE_RETURN *psRetOUT,
+			   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_UINT32 ui32Offset;
+	IMG_VOID *pvSyncInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_SYNCPOL);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+						   psPDumpSyncPolIN->psKernelSyncInfo,
+						   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	if(psPDumpSyncPolIN->bIsRead)
+	{
+		ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+	}
+	else
+	{
+		ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
+	}
+
+	psRetOUT->eError =
+		PDumpMemPolKM(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM,
+					  ui32Offset,
+					  psPDumpSyncPolIN->ui32Value,
+					  psPDumpSyncPolIN->ui32Mask,
+					  PDUMP_POLL_OPERATOR_EQUAL,
+					  0,
+					  MAKEUNIQUETAG(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM));
+
+	return 0;
+}
+
+static IMG_INT
+PDumpPDRegBW(IMG_UINT32 ui32BridgeID,
+			 PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG *psPDumpPDRegDumpIN,
+			 PVRSRV_BRIDGE_RETURN *psRetOUT,
+			 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_PDREG);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	PDumpPDReg(psPDumpPDRegDumpIN->sHWReg.ui32RegAddr,
+			   psPDumpPDRegDumpIN->sHWReg.ui32RegVal,
+			   PDUMP_PD_UNIQUETAG);
+
+	psRetOUT->eError = PVRSRV_OK;
+	return 0;
+}
+
+static IMG_INT
+PDumpCycleCountRegReadBW(IMG_UINT32 ui32BridgeID,
+						 PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ *psPDumpCycleCountRegReadIN,
+						 PVRSRV_BRIDGE_RETURN *psRetOUT,
+						 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	PDumpCycleCountRegRead(psPDumpCycleCountRegReadIN->ui32RegOffset,
+						   psPDumpCycleCountRegReadIN->bLastFrame);
+
+	psRetOUT->eError = PVRSRV_OK;
+
+	return 0;
+}
+
+static IMG_INT
+PDumpPDDevPAddrBW(IMG_UINT32 ui32BridgeID,
+				  PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR *psPDumpPDDevPAddrIN,
+				  PVRSRV_BRIDGE_RETURN *psRetOUT,
+				  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &pvMemInfo,
+						   psPDumpPDDevPAddrIN->hKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PDumpPDDevPAddrKM((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo,
+						  psPDumpPDDevPAddrIN->ui32Offset,
+						  psPDumpPDDevPAddrIN->sPDDevPAddr,
+						  MAKEUNIQUETAG(pvMemInfo),
+						  PDUMP_PD_UNIQUETAG);
+	return 0;
+}
+
+static IMG_INT
+PDumpStartInitPhaseBW(IMG_UINT32 ui32BridgeID,
+					  IMG_VOID *psBridgeIn,
+					  PVRSRV_BRIDGE_RETURN *psRetOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_STARTINITPHASE);
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	psRetOUT->eError = PDumpStartInitPhaseKM();
+
+	return 0;
+}
+
+static IMG_INT
+PDumpStopInitPhaseBW(IMG_UINT32 ui32BridgeID,
+					  IMG_VOID *psBridgeIn,
+					  PVRSRV_BRIDGE_RETURN *psRetOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_STOPINITPHASE);
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	psRetOUT->eError = PDumpStopInitPhaseKM();
+
+	return 0;
+}
+
+#endif
+
+
+static IMG_INT
+PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
+					PVRSRV_BRIDGE_IN_GET_MISC_INFO *psGetMiscInfoIN,
+					PVRSRV_BRIDGE_OUT_GET_MISC_INFO *psGetMiscInfoOUT,
+					PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_ERROR eError;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_MISC_INFO);
+
+	OSMemCopy(&psGetMiscInfoOUT->sMiscInfo,
+	          &psGetMiscInfoIN->sMiscInfo,
+	          sizeof(PVRSRV_MISC_INFO));
+
+	if (((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0) &&
+	    ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0))
+	{
+
+		psGetMiscInfoOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+
+	if (((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0) ||
+	    ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0))
+	{
+
+		ASSIGN_AND_EXIT_ON_ERROR(psGetMiscInfoOUT->eError,
+				    OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+		                    psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen,
+		                    (IMG_VOID **)&psGetMiscInfoOUT->sMiscInfo.pszMemoryStr, 0,
+							"Output string buffer"));
+
+		psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
+
+
+		eError = CopyToUserWrapper(psPerProc, ui32BridgeID,
+		                           psGetMiscInfoIN->sMiscInfo.pszMemoryStr,
+		                           psGetMiscInfoOUT->sMiscInfo.pszMemoryStr,
+		                           psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen);
+
+
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+		          psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen,
+		         (IMG_VOID *)psGetMiscInfoOUT->sMiscInfo.pszMemoryStr, 0);
+		psGetMiscInfoOUT->sMiscInfo.pszMemoryStr = IMG_NULL;
+
+
+		psGetMiscInfoOUT->sMiscInfo.pszMemoryStr = psGetMiscInfoIN->sMiscInfo.pszMemoryStr;
+
+		if(eError != PVRSRV_OK)
+		{
+
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoBW Error copy to user"));
+			return -EFAULT;
+		}
+	}
+	else
+	{
+		psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
+	}
+
+
+	if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+	if (psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT)
+	{
+		psGetMiscInfoOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+													&psGetMiscInfoOUT->sMiscInfo.sGlobalEventObject.hOSEventKM,
+													psGetMiscInfoOUT->sMiscInfo.sGlobalEventObject.hOSEventKM,
+													PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+													PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+			if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+			{
+				return 0;
+			}
+	}
+
+	if (psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle)
+	{
+
+		psGetMiscInfoOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+						  &psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle,
+						  psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle,
+						  PVRSRV_HANDLE_TYPE_SOC_TIMER,
+						  PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+		if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVConnectBW(IMG_UINT32 ui32BridgeID,
+				IMG_VOID *psBridgeIn,
+				PVRSRV_BRIDGE_OUT_CONNECT_SERVICES *psConnectServicesOUT,
+				PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CONNECT_SERVICES);
+
+	psConnectServicesOUT->hKernelServices = psPerProc->hPerProcData;
+	psConnectServicesOUT->eError = PVRSRV_OK;
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVDisconnectBW(IMG_UINT32 ui32BridgeID,
+				   IMG_VOID *psBridgeIn,
+				   PVRSRV_BRIDGE_RETURN *psRetOUT,
+				   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DISCONNECT_SERVICES);
+
+
+	psRetOUT->eError = PVRSRV_OK;
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVEnumerateDCBW(IMG_UINT32 ui32BridgeID,
+					PVRSRV_BRIDGE_IN_ENUMCLASS *psEnumDispClassIN,
+					PVRSRV_BRIDGE_OUT_ENUMCLASS *psEnumDispClassOUT,
+					PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_CLASS);
+
+	psEnumDispClassOUT->eError =
+		PVRSRVEnumerateDCKM(psEnumDispClassIN->sDeviceClass,
+							&psEnumDispClassOUT->ui32NumDevices,
+							&psEnumDispClassOUT->ui32DevID[0]);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVOpenDCDeviceBW(IMG_UINT32 ui32BridgeID,
+					 PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE *psOpenDispClassDeviceIN,
+					 PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE *psOpenDispClassDeviceOUT,
+					 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hDispClassInfoInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psOpenDispClassDeviceOUT->eError, psPerProc, 1);
+
+	psOpenDispClassDeviceOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psOpenDispClassDeviceIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psOpenDispClassDeviceOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psOpenDispClassDeviceOUT->eError =
+		PVRSRVOpenDCDeviceKM(psPerProc,
+							 psOpenDispClassDeviceIN->ui32DeviceID,
+							 hDevCookieInt,
+							 &hDispClassInfoInt);
+
+	if(psOpenDispClassDeviceOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psOpenDispClassDeviceOUT->hDeviceKM,
+					  hDispClassInfoInt,
+					  PVRSRV_HANDLE_TYPE_DISP_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+	COMMIT_HANDLE_BATCH_OR_ERROR(psOpenDispClassDeviceOUT->eError, psPerProc);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVCloseDCDeviceBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE *psCloseDispClassDeviceIN,
+					  PVRSRV_BRIDGE_RETURN *psRetOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfoInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfoInt,
+						   psCloseDispClassDeviceIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = PVRSRVCloseDCDeviceKM(pvDispClassInfoInt, IMG_FALSE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psCloseDispClassDeviceIN->hDeviceKM,
+							PVRSRV_HANDLE_TYPE_DISP_INFO);
+	return 0;
+}
+
+static IMG_INT
+PVRSRVEnumDCFormatsBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS *psEnumDispClassFormatsIN,
+					  PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS *psEnumDispClassFormatsOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfoInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS);
+
+	psEnumDispClassFormatsOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfoInt,
+						   psEnumDispClassFormatsIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psEnumDispClassFormatsOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psEnumDispClassFormatsOUT->eError =
+		PVRSRVEnumDCFormatsKM(pvDispClassInfoInt,
+							  &psEnumDispClassFormatsOUT->ui32Count,
+							  psEnumDispClassFormatsOUT->asFormat);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVEnumDCDimsBW(IMG_UINT32 ui32BridgeID,
+				   PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS *psEnumDispClassDimsIN,
+				   PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS *psEnumDispClassDimsOUT,
+				   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfoInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS);
+
+	psEnumDispClassDimsOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfoInt,
+						   psEnumDispClassDimsIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+	if(psEnumDispClassDimsOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psEnumDispClassDimsOUT->eError =
+		PVRSRVEnumDCDimsKM(pvDispClassInfoInt,
+						   &psEnumDispClassDimsIN->sFormat,
+						   &psEnumDispClassDimsOUT->ui32Count,
+						   psEnumDispClassDimsOUT->asDim);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVGetDCSystemBufferBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferIN,
+						  PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hBufferInt;
+	IMG_VOID *pvDispClassInfoInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psGetDispClassSysBufferOUT->eError, psPerProc, 1);
+
+	psGetDispClassSysBufferOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfoInt,
+						   psGetDispClassSysBufferIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psGetDispClassSysBufferOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetDispClassSysBufferOUT->eError =
+		PVRSRVGetDCSystemBufferKM(pvDispClassInfoInt,
+								  &hBufferInt);
+
+	if(psGetDispClassSysBufferOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+						 &psGetDispClassSysBufferOUT->hBuffer,
+						 hBufferInt,
+						 PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+						 (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE | PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+						 psGetDispClassSysBufferIN->hDeviceKM);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psGetDispClassSysBufferOUT->eError, psPerProc);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVGetDCInfoBW(IMG_UINT32 ui32BridgeID,
+				  PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO *psGetDispClassInfoIN,
+				  PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO *psGetDispClassInfoOUT,
+				  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_INFO);
+
+	psGetDispClassInfoOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psGetDispClassInfoIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psGetDispClassInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetDispClassInfoOUT->eError =
+		PVRSRVGetDCInfoKM(pvDispClassInfo,
+						  &psGetDispClassInfoOUT->sDisplayInfo);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVCreateDCSwapChainBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN *psCreateDispClassSwapChainIN,
+						  PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN *psCreateDispClassSwapChainOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+	IMG_HANDLE hSwapChainInt;
+	IMG_UINT32	ui32SwapChainID;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psCreateDispClassSwapChainOUT->eError, psPerProc, 1);
+
+	psCreateDispClassSwapChainOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psCreateDispClassSwapChainIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+	if(psCreateDispClassSwapChainOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+	ui32SwapChainID = psCreateDispClassSwapChainIN->ui32SwapChainID;
+
+	psCreateDispClassSwapChainOUT->eError =
+		PVRSRVCreateDCSwapChainKM(psPerProc, pvDispClassInfo,
+								  psCreateDispClassSwapChainIN->ui32Flags,
+								  &psCreateDispClassSwapChainIN->sDstSurfAttrib,
+								  &psCreateDispClassSwapChainIN->sSrcSurfAttrib,
+								  psCreateDispClassSwapChainIN->ui32BufferCount,
+								  psCreateDispClassSwapChainIN->ui32OEMFlags,
+								  &hSwapChainInt,
+								  &ui32SwapChainID);
+
+	if(psCreateDispClassSwapChainOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+	psCreateDispClassSwapChainOUT->ui32SwapChainID = ui32SwapChainID;
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+					  &psCreateDispClassSwapChainOUT->hSwapChain,
+					  hSwapChainInt,
+					  PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+					  psCreateDispClassSwapChainIN->hDeviceKM);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psCreateDispClassSwapChainOUT->eError, psPerProc);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVDestroyDCSwapChainBW(IMG_UINT32 ui32BridgeID,
+						   PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN *psDestroyDispClassSwapChainIN,
+						   PVRSRV_BRIDGE_RETURN *psRetOUT,
+						   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvSwapChain;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSwapChain,
+						   psDestroyDispClassSwapChainIN->hSwapChain,
+						   PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVDestroyDCSwapChainKM(pvSwapChain);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psDestroyDispClassSwapChainIN->hSwapChain,
+							PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCDstRectBW(IMG_UINT32 ui32BridgeID,
+					 PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT *psSetDispClassDstRectIN,
+					 PVRSRV_BRIDGE_RETURN *psRetOUT,
+					 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+	IMG_VOID *pvSwapChain;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psSetDispClassDstRectIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvSwapChain,
+						   psSetDispClassDstRectIN->hSwapChain,
+						   PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVSetDCDstRectKM(pvDispClassInfo,
+							 pvSwapChain,
+							 &psSetDispClassDstRectIN->sRect);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCSrcRectBW(IMG_UINT32 ui32BridgeID,
+					 PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT *psSetDispClassSrcRectIN,
+					 PVRSRV_BRIDGE_RETURN *psRetOUT,
+					 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+	IMG_VOID *pvSwapChain;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psSetDispClassSrcRectIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvSwapChain,
+						   psSetDispClassSrcRectIN->hSwapChain,
+						   PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVSetDCSrcRectKM(pvDispClassInfo,
+							 pvSwapChain,
+							 &psSetDispClassSrcRectIN->sRect);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCDstColourKeyBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY *psSetDispClassColKeyIN,
+						  PVRSRV_BRIDGE_RETURN *psRetOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+	IMG_VOID *pvSwapChain;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psSetDispClassColKeyIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvSwapChain,
+						   psSetDispClassColKeyIN->hSwapChain,
+						   PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVSetDCDstColourKeyKM(pvDispClassInfo,
+								  pvSwapChain,
+								  psSetDispClassColKeyIN->ui32CKColour);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCSrcColourKeyBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY *psSetDispClassColKeyIN,
+						  PVRSRV_BRIDGE_RETURN *psRetOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+	IMG_VOID *pvSwapChain;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psSetDispClassColKeyIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvSwapChain,
+						   psSetDispClassColKeyIN->hSwapChain,
+						   PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVSetDCSrcColourKeyKM(pvDispClassInfo,
+								  pvSwapChain,
+								  psSetDispClassColKeyIN->ui32CKColour);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVGetDCBuffersBW(IMG_UINT32 ui32BridgeID,
+					 PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS *psGetDispClassBuffersIN,
+					 PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS *psGetDispClassBuffersOUT,
+					 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+	IMG_VOID *pvSwapChain;
+	IMG_UINT32 i;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psGetDispClassBuffersOUT->eError, psPerProc, PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+	psGetDispClassBuffersOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psGetDispClassBuffersIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetDispClassBuffersOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvSwapChain,
+						   psGetDispClassBuffersIN->hSwapChain,
+						   PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+	if(psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetDispClassBuffersOUT->eError =
+		PVRSRVGetDCBuffersKM(pvDispClassInfo,
+							 pvSwapChain,
+							 &psGetDispClassBuffersOUT->ui32BufferCount,
+							 psGetDispClassBuffersOUT->ahBuffer);
+	if (psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	PVR_ASSERT(psGetDispClassBuffersOUT->ui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+	for(i = 0; i < psGetDispClassBuffersOUT->ui32BufferCount; i++)
+	{
+		IMG_HANDLE hBufferExt;
+
+
+		PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+							 &hBufferExt,
+							 psGetDispClassBuffersOUT->ahBuffer[i],
+							 PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+							 (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE | PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+							 psGetDispClassBuffersIN->hSwapChain);
+
+		psGetDispClassBuffersOUT->ahBuffer[i] = hBufferExt;
+	}
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psGetDispClassBuffersOUT->eError, psPerProc);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVSwapToDCBufferBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER *psSwapDispClassBufferIN,
+					   PVRSRV_BRIDGE_RETURN *psRetOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+	IMG_VOID *pvSwapChainBuf;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psSwapDispClassBufferIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+						   &pvSwapChainBuf,
+						   psSwapDispClassBufferIN->hBuffer,
+						   PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+						   psSwapDispClassBufferIN->hDeviceKM);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVSwapToDCBufferKM(pvDispClassInfo,
+							   pvSwapChainBuf,
+							   psSwapDispClassBufferIN->ui32SwapInterval,
+							   psSwapDispClassBufferIN->hPrivateTag,
+							   psSwapDispClassBufferIN->ui32ClipRectCount,
+							   psSwapDispClassBufferIN->sClipRect);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVSwapToDCSystemBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM *psSwapDispClassSystemIN,
+					   PVRSRV_BRIDGE_RETURN *psRetOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+	IMG_VOID *pvSwapChain;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psSwapDispClassSystemIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+						   &pvSwapChain,
+						   psSwapDispClassSystemIN->hSwapChain,
+						   PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+						   psSwapDispClassSystemIN->hDeviceKM);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+	psRetOUT->eError =
+		PVRSRVSwapToDCSystemKM(pvDispClassInfo,
+							   pvSwapChain);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVOpenBCDeviceBW(IMG_UINT32 ui32BridgeID,
+					 PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE *psOpenBufferClassDeviceIN,
+					 PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE *psOpenBufferClassDeviceOUT,
+					 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hBufClassInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psOpenBufferClassDeviceOUT->eError, psPerProc, 1);
+
+	psOpenBufferClassDeviceOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psOpenBufferClassDeviceIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psOpenBufferClassDeviceOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psOpenBufferClassDeviceOUT->eError =
+		PVRSRVOpenBCDeviceKM(psPerProc,
+							 psOpenBufferClassDeviceIN->ui32DeviceID,
+							 hDevCookieInt,
+							 &hBufClassInfo);
+	if(psOpenBufferClassDeviceOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psOpenBufferClassDeviceOUT->hDeviceKM,
+					  hBufClassInfo,
+					  PVRSRV_HANDLE_TYPE_BUF_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psOpenBufferClassDeviceOUT->eError, psPerProc);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVCloseBCDeviceBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE *psCloseBufferClassDeviceIN,
+					  PVRSRV_BRIDGE_RETURN *psRetOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvBufClassInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvBufClassInfo,
+						   psCloseBufferClassDeviceIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_BUF_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVCloseBCDeviceKM(pvBufClassInfo, IMG_FALSE);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+										   psCloseBufferClassDeviceIN->hDeviceKM,
+										   PVRSRV_HANDLE_TYPE_BUF_INFO);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVGetBCInfoBW(IMG_UINT32 ui32BridgeID,
+				  PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO *psGetBufferClassInfoIN,
+				  PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO *psGetBufferClassInfoOUT,
+				  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvBufClassInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO);
+
+	psGetBufferClassInfoOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvBufClassInfo,
+						   psGetBufferClassInfoIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_BUF_INFO);
+	if(psGetBufferClassInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetBufferClassInfoOUT->eError =
+		PVRSRVGetBCInfoKM(pvBufClassInfo,
+						  &psGetBufferClassInfoOUT->sBufferInfo);
+	return 0;
+}
+
+static IMG_INT
+PVRSRVGetBCBufferBW(IMG_UINT32 ui32BridgeID,
+					PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferIN,
+					PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferOUT,
+					PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvBufClassInfo;
+	IMG_HANDLE hBufferInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psGetBufferClassBufferOUT->eError, psPerProc, 1);
+
+	psGetBufferClassBufferOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvBufClassInfo,
+						   psGetBufferClassBufferIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_BUF_INFO);
+	if(psGetBufferClassBufferOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetBufferClassBufferOUT->eError =
+		PVRSRVGetBCBufferKM(pvBufClassInfo,
+							psGetBufferClassBufferIN->ui32BufferIndex,
+							&hBufferInt);
+
+	if(psGetBufferClassBufferOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+						 &psGetBufferClassBufferOUT->hBuffer,
+						 hBufferInt,
+						 PVRSRV_HANDLE_TYPE_BUF_BUFFER,
+						 (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE |  PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+						 psGetBufferClassBufferIN->hDeviceKM);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psGetBufferClassBufferOUT->eError, psPerProc);
+
+	return 0;
+}
+
+
+static IMG_INT 
+PVRSRVGetBCBufferIdFromTagBW(IMG_UINT32 ui32BridgeID,
+					PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferIN,
+					PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferOUT,
+					PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvBufClassInfo = IMG_NULL;
+	IMG_HANDLE pidx = IMG_NULL;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER_ID_FROM_TAG);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psGetBufferClassBufferOUT->eError, psPerProc, 1);
+
+	psGetBufferClassBufferOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvBufClassInfo,
+						   psGetBufferClassBufferIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_BUF_INFO);
+	if(psGetBufferClassBufferOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetBufferClassBufferOUT->eError =
+		PVRSRVGetBCBufferIdFromTagKM(pvBufClassInfo,
+							psGetBufferClassBufferIN->ui32BufferIndex,
+							&pidx);
+
+	if(psGetBufferClassBufferOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetBufferClassBufferOUT->hBuffer = pidx;
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVAllocSharedSysMemoryBW(IMG_UINT32 ui32BridgeID,
+							 PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM *psAllocSharedSysMemIN,
+							 PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM *psAllocSharedSysMemOUT,
+							 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psAllocSharedSysMemOUT->eError, psPerProc, 1);
+
+	psAllocSharedSysMemOUT->eError =
+		PVRSRVAllocSharedSysMemoryKM(psPerProc,
+									 psAllocSharedSysMemIN->ui32Flags,
+									 psAllocSharedSysMemIN->ui32Size,
+									 &psKernelMemInfo);
+	if(psAllocSharedSysMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	OSMemSet(&psAllocSharedSysMemOUT->sClientMemInfo,
+			 0,
+			 sizeof(psAllocSharedSysMemOUT->sClientMemInfo));
+
+	psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddrKM =
+			psKernelMemInfo->pvLinAddrKM;
+
+	psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddr = 0;
+	psAllocSharedSysMemOUT->sClientMemInfo.ui32Flags =
+		psKernelMemInfo->ui32Flags;
+	psAllocSharedSysMemOUT->sClientMemInfo.ui32AllocSize =
+		psKernelMemInfo->ui32AllocSize;
+	psAllocSharedSysMemOUT->sClientMemInfo.hMappingInfo = psKernelMemInfo->sMemBlk.hOSMemHandle;
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psAllocSharedSysMemOUT->sClientMemInfo.hKernelMemInfo,
+					  psKernelMemInfo,
+					  PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psAllocSharedSysMemOUT->eError, psPerProc);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVFreeSharedSysMemoryBW(IMG_UINT32 ui32BridgeID,
+							PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM *psFreeSharedSysMemIN,
+							PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM *psFreeSharedSysMemOUT,
+							PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM);
+
+	psFreeSharedSysMemOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   (IMG_VOID **)&psKernelMemInfo,
+						   psFreeSharedSysMemIN->psKernelMemInfo,
+																   PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+
+	if(psFreeSharedSysMemOUT->eError != PVRSRV_OK)
+		return 0;
+
+	psFreeSharedSysMemOUT->eError =
+		PVRSRVFreeSharedSysMemoryKM(psKernelMemInfo);
+	if(psFreeSharedSysMemOUT->eError != PVRSRV_OK)
+		return 0;
+
+	psFreeSharedSysMemOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psFreeSharedSysMemIN->psKernelMemInfo,
+							PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+	return 0;
+}
+
+static IMG_INT
+PVRSRVMapMemInfoMemBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM *psMapMemInfoMemIN,
+					  PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM *psMapMemInfoMemOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+	PVRSRV_HANDLE_TYPE eHandleType;
+	IMG_HANDLE	hParent;
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_MEMINFO_MEM);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psMapMemInfoMemOUT->eError, psPerProc, 2);
+
+	psMapMemInfoMemOUT->eError =
+		PVRSRVLookupHandleAnyType(psPerProc->psHandleBase,
+						   (IMG_VOID **)&psKernelMemInfo,
+						   &eHandleType,
+						   psMapMemInfoMemIN->hKernelMemInfo);
+	if(psMapMemInfoMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	switch (eHandleType)
+	{
+#if defined(PVR_SECURE_HANDLES)
+		case PVRSRV_HANDLE_TYPE_MEM_INFO:
+		case PVRSRV_HANDLE_TYPE_MEM_INFO_REF:
+		case PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO:
+#else
+		case PVRSRV_HANDLE_TYPE_NONE:
+#endif
+			break;
+		default:
+			psMapMemInfoMemOUT->eError = PVRSRV_ERROR_GENERIC;
+			return 0;
+	}
+
+
+	psMapMemInfoMemOUT->eError =
+		PVRSRVGetParentHandle(psPerProc->psHandleBase,
+					&hParent,
+					psMapMemInfoMemIN->hKernelMemInfo,
+					eHandleType);
+	if (psMapMemInfoMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+	if (hParent == IMG_NULL)
+	{
+		hParent = psMapMemInfoMemIN->hKernelMemInfo;
+	}
+
+	OSMemSet(&psMapMemInfoMemOUT->sClientMemInfo,
+			 0,
+			 sizeof(psMapMemInfoMemOUT->sClientMemInfo));
+
+	psMapMemInfoMemOUT->sClientMemInfo.pvLinAddrKM =
+			psKernelMemInfo->pvLinAddrKM;
+
+	psMapMemInfoMemOUT->sClientMemInfo.pvLinAddr = 0;
+	psMapMemInfoMemOUT->sClientMemInfo.sDevVAddr =
+		psKernelMemInfo->sDevVAddr;
+	psMapMemInfoMemOUT->sClientMemInfo.ui32Flags =
+		psKernelMemInfo->ui32Flags;
+	psMapMemInfoMemOUT->sClientMemInfo.ui32AllocSize =
+		psKernelMemInfo->ui32AllocSize;
+	psMapMemInfoMemOUT->sClientMemInfo.hMappingInfo = psKernelMemInfo->sMemBlk.hOSMemHandle;
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+					  &psMapMemInfoMemOUT->sClientMemInfo.hKernelMemInfo,
+					  psKernelMemInfo,
+					  PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+					  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+					  hParent);
+
+	if(psKernelMemInfo->ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)
+	{
+
+		OSMemSet(&psMapMemInfoMemOUT->sClientSyncInfo,
+				 0,
+				 sizeof (PVRSRV_CLIENT_SYNC_INFO));
+		psMapMemInfoMemOUT->psKernelSyncInfo = IMG_NULL;
+	}
+	else
+	{
+
+		psMapMemInfoMemOUT->sClientSyncInfo.psSyncData =
+			psKernelMemInfo->psKernelSyncInfo->psSyncData;
+		psMapMemInfoMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+			psKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+		psMapMemInfoMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+			psKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+		psMapMemInfoMemOUT->sClientSyncInfo.hMappingInfo =
+			psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+		psMapMemInfoMemOUT->sClientMemInfo.psClientSyncInfo = &psMapMemInfoMemOUT->sClientSyncInfo;
+
+		PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+							 &psMapMemInfoMemOUT->sClientSyncInfo.hKernelSyncInfo,
+							 psKernelMemInfo->psKernelSyncInfo,
+							 PVRSRV_HANDLE_TYPE_SYNC_INFO,
+							 PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+							 psMapMemInfoMemOUT->sClientMemInfo.hKernelMemInfo);
+	}
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psMapMemInfoMemOUT->eError, psPerProc);
+
+	return 0;
+}
+
+
+
+static IMG_INT
+MMU_GetPDDevPAddrBW(IMG_UINT32 ui32BridgeID,
+					PVRSRV_BRIDGE_IN_GETMMU_PD_DEVPADDR *psGetMmuPDDevPAddrIN,
+					PVRSRV_BRIDGE_OUT_GETMMU_PD_DEVPADDR *psGetMmuPDDevPAddrOUT,
+					PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevMemContextInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GETMMU_PD_DEVPADDR);
+
+	psGetMmuPDDevPAddrOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+						   psGetMmuPDDevPAddrIN->hDevMemContext,
+						   PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+	if(psGetMmuPDDevPAddrOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetMmuPDDevPAddrOUT->sPDDevPAddr =
+		BM_GetDeviceNode(hDevMemContextInt)->pfnMMUGetPDDevPAddr(BM_GetMMUContextFromMemContext(hDevMemContextInt));
+	if(psGetMmuPDDevPAddrOUT->sPDDevPAddr.uiAddr)
+	{
+		psGetMmuPDDevPAddrOUT->eError = PVRSRV_OK;
+	}
+	else
+	{
+		psGetMmuPDDevPAddrOUT->eError = PVRSRV_ERROR_GENERIC;
+	}
+	return 0;
+}
+
+
+
+IMG_INT
+DummyBW(IMG_UINT32 ui32BridgeID,
+		IMG_VOID *psBridgeIn,
+		IMG_VOID *psBridgeOut,
+		PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+#if !defined(DEBUG)
+	PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+#endif
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+	PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+#if defined(DEBUG_BRIDGE_KM)
+	PVR_DPF((PVR_DBG_ERROR, "%s: BRIDGE ERROR: BridgeID %lu (%s) mapped to "
+			 "Dummy Wrapper (probably not what you want!)",
+			 __FUNCTION__, ui32BridgeID, g_BridgeDispatchTable[ui32BridgeID].pszIOCName));
+#else
+	PVR_DPF((PVR_DBG_ERROR, "%s: BRIDGE ERROR: BridgeID %lu mapped to "
+			 "Dummy Wrapper (probably not what you want!)",
+			 __FUNCTION__, ui32BridgeID));
+#endif
+	return -ENOTTY;
+}
+
+
+IMG_VOID
+_SetDispatchTableEntry(IMG_UINT32 ui32Index,
+					   const IMG_CHAR *pszIOCName,
+					   BridgeWrapperFunction pfFunction,
+					   const IMG_CHAR *pszFunctionName)
+{
+	static IMG_UINT32 ui32PrevIndex = ~0UL;
+#if !defined(DEBUG)
+	PVR_UNREFERENCED_PARAMETER(pszIOCName);
+#endif
+#if !defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE) && !defined(DEBUG_BRIDGE_KM)
+	PVR_UNREFERENCED_PARAMETER(pszFunctionName);
+#endif
+
+#if defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE)
+
+	PVR_DPF((PVR_DBG_WARNING, "%s: %d %s %s", __FUNCTION__, ui32Index, pszIOCName, pszFunctionName));
+#endif
+
+
+	if(g_BridgeDispatchTable[ui32Index].pfFunction)
+	{
+#if defined(DEBUG_BRIDGE_KM)
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry for %s",
+				 __FUNCTION__, pszIOCName, g_BridgeDispatchTable[ui32Index].pszIOCName));
+#else
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry (index=%lu)",
+				 __FUNCTION__, pszIOCName, ui32Index));
+#endif
+		PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue.",
+				__FUNCTION__));
+	}
+
+
+	if((ui32PrevIndex != ~0UL) &&
+	   ((ui32Index >= ui32PrevIndex + DISPATCH_TABLE_GAP_THRESHOLD) ||
+		(ui32Index <= ui32PrevIndex)))
+	{
+#if defined(DEBUG_BRIDGE_KM)
+		PVR_DPF((PVR_DBG_WARNING,
+				 "%s: There is a gap in the dispatch table between indices %lu (%s) and %lu (%s)",
+				 __FUNCTION__, ui32PrevIndex, g_BridgeDispatchTable[ui32PrevIndex].pszIOCName,
+				 ui32Index, pszIOCName));
+#else
+		PVR_DPF((PVR_DBG_WARNING,
+				 "%s: There is a gap in the dispatch table between indices %u and %u (%s)",
+				 __FUNCTION__, (IMG_UINT)ui32PrevIndex, (IMG_UINT)ui32Index, pszIOCName));
+#endif
+		PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue.",
+				__FUNCTION__));
+	}
+
+	g_BridgeDispatchTable[ui32Index].pfFunction = pfFunction;
+#if defined(DEBUG_BRIDGE_KM)
+	g_BridgeDispatchTable[ui32Index].pszIOCName = pszIOCName;
+	g_BridgeDispatchTable[ui32Index].pszFunctionName = pszFunctionName;
+	g_BridgeDispatchTable[ui32Index].ui32CallCount = 0;
+	g_BridgeDispatchTable[ui32Index].ui32CopyFromUserTotalBytes = 0;
+#endif
+
+	ui32PrevIndex = ui32Index;
+}
+
+static IMG_INT
+PVRSRVInitSrvConnectBW(IMG_UINT32 ui32BridgeID,
+					   IMG_VOID *psBridgeIn,
+					   PVRSRV_BRIDGE_RETURN *psRetOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_INITSRV_CONNECT);
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+	if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
+	{
+		psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+		return 0;
+	}
+
+#if defined (__linux__)
+	PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_TRUE);
+#endif
+	psPerProc->bInitProcess = IMG_TRUE;
+
+	psRetOUT->eError = PVRSRV_OK;
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVInitSrvDisconnectBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT *psInitSrvDisconnectIN,
+						  PVRSRV_BRIDGE_RETURN *psRetOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_INITSRV_DISCONNECT);
+
+	if(!psPerProc->bInitProcess)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+		return 0;
+	}
+
+	psPerProc->bInitProcess = IMG_FALSE;
+
+	PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_FALSE);
+	PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RAN, IMG_TRUE);
+
+	psRetOUT->eError = PVRSRVFinaliseSystem(psInitSrvDisconnectIN->bInitSuccesful);
+
+	PVRSRVSetInitServerState( PVRSRV_INIT_SERVER_SUCCESSFUL,
+				(((psRetOUT->eError == PVRSRV_OK) && (psInitSrvDisconnectIN->bInitSuccesful)))
+				? IMG_TRUE : IMG_FALSE);
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectWaitBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAIT *psEventObjectWaitIN,
+						  PVRSRV_BRIDGE_RETURN *psRetOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hOSEventKM;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_WAIT);
+
+	psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hOSEventKM,
+						   psEventObjectWaitIN->hOSEventKM,
+						   PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = OSEventObjectWait(hOSEventKM);
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectOpenBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN *psEventObjectOpenIN,
+						  PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN *psEventObjectOpenOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_OPEN);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psEventObjectOpenOUT->eError, psPerProc, 1);
+
+	psEventObjectOpenOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &psEventObjectOpenIN->sEventObject.hOSEventKM,
+						   psEventObjectOpenIN->sEventObject.hOSEventKM,
+						   PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+
+	if(psEventObjectOpenOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psEventObjectOpenOUT->eError = OSEventObjectOpen(&psEventObjectOpenIN->sEventObject, &psEventObjectOpenOUT->hOSEvent);
+
+	if(psEventObjectOpenOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psEventObjectOpenOUT->hOSEvent,
+					  psEventObjectOpenOUT->hOSEvent,
+					  PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+					  PVRSRV_HANDLE_ALLOC_FLAG_MULTI);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psEventObjectOpenOUT->eError, psPerProc);
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectCloseBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE *psEventObjectCloseIN,
+						  PVRSRV_BRIDGE_RETURN *psRetOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hOSEventKM;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &psEventObjectCloseIN->sEventObject.hOSEventKM,
+						   psEventObjectCloseIN->sEventObject.hOSEventKM,
+						   PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &hOSEventKM,
+						   psEventObjectCloseIN->hOSEventKM,
+						   PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = OSEventObjectClose(&psEventObjectCloseIN->sEventObject, hOSEventKM);
+
+	return 0;
+}
+
+
+typedef struct _MODIFY_SYNC_OP_INFO
+{
+	PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+	IMG_UINT32 	ui32ModifyFlags;
+	IMG_UINT32	ui32ReadOpsPendingSnapShot;
+	IMG_UINT32	ui32WriteOpsPendingSnapShot;
+} MODIFY_SYNC_OP_INFO;
+
+
+static PVRSRV_ERROR ModifyCompleteSyncOpsCallBack(IMG_PVOID		pvParam,
+													IMG_UINT32	ui32Param)
+{
+	MODIFY_SYNC_OP_INFO		*psModSyncOpInfo;
+	PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+	if (!pvParam)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "ModifyCompleteSyncOpsCallBack: invalid parameter"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psModSyncOpInfo = (MODIFY_SYNC_OP_INFO*)pvParam;
+	psKernelSyncInfo = psModSyncOpInfo->psKernelSyncInfo;
+
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		if((psModSyncOpInfo->ui32WriteOpsPendingSnapShot == psKernelSyncInfo->psSyncData->ui32WriteOpsComplete)
+		&& (psModSyncOpInfo->ui32ReadOpsPendingSnapShot == psKernelSyncInfo->psSyncData->ui32ReadOpsComplete))
+		{
+			goto OpFlushedComplete;
+		}
+		PVR_DPF((PVR_DBG_ERROR, "ModifyCompleteSyncOpsCallBack: waiting for old Ops to flush"));
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	PVR_DPF((PVR_DBG_ERROR, "ModifyCompleteSyncOpsCallBack: waiting for old Ops to flush timed out"));
+
+	return PVRSRV_ERROR_TIMEOUT;
+
+OpFlushedComplete:
+
+
+	if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
+	{
+		psKernelSyncInfo->psSyncData->ui32WriteOpsComplete++;
+	}
+
+
+	if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC)
+	{
+		psKernelSyncInfo->psSyncData->ui32ReadOpsComplete++;
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 	sizeof(MODIFY_SYNC_OP_INFO), (IMG_VOID *)psModSyncOpInfo, 0);
+
+
+
+	PVRSRVCommandCompleteCallbacks();
+
+	return PVRSRV_OK;
+}
+
+
+static IMG_INT
+PVRSRVModifyPendingSyncOpsBW(IMG_UINT32									ui32BridgeID,
+						      PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS	*psModifySyncOpsIN,
+							  PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS	*psModifySyncOpsOUT,
+							  PVRSRV_PER_PROCESS_DATA					*psPerProc)
+{
+	IMG_HANDLE				hKernelSyncInfo;
+	PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+	MODIFY_SYNC_OP_INFO		*psModSyncOpInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS);
+
+	psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+													&hKernelSyncInfo,
+													psModifySyncOpsIN->hKernelSyncInfo,
+													PVRSRV_HANDLE_TYPE_SYNC_INFO);
+	if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyPendingSyncOpsBW: PVRSRVLookupHandle failed"));
+		return 0;
+	}
+
+	psKernelSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)hKernelSyncInfo;
+
+	if(psKernelSyncInfo->hResItem != IMG_NULL)
+	{
+
+		psModifySyncOpsOUT->eError = PVRSRV_ERROR_RETRY;
+		return 0;
+	}
+
+	ASSIGN_AND_EXIT_ON_ERROR(psModifySyncOpsOUT->eError,
+			  OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+			  sizeof(MODIFY_SYNC_OP_INFO),
+			  (IMG_VOID **)&psModSyncOpInfo, 0,
+			  "ModSyncOpInfo (MODIFY_SYNC_OP_INFO)"));
+
+
+	psModSyncOpInfo->psKernelSyncInfo = psKernelSyncInfo;
+	psModSyncOpInfo->ui32ModifyFlags = psModifySyncOpsIN->ui32ModifyFlags;
+	psModSyncOpInfo->ui32ReadOpsPendingSnapShot = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+	psModSyncOpInfo->ui32WriteOpsPendingSnapShot = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+
+
+
+	psModifySyncOpsOUT->ui32ReadOpsPending = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+	psModifySyncOpsOUT->ui32WriteOpsPending = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+
+	if(psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
+	{
+		psKernelSyncInfo->psSyncData->ui32WriteOpsPending++;
+	}
+
+	if(psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC)
+	{
+		psKernelSyncInfo->psSyncData->ui32ReadOpsPending++;
+	}
+
+	psKernelSyncInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+													RESMAN_TYPE_MODIFY_SYNC_OPS,
+													psModSyncOpInfo,
+													0,
+													ModifyCompleteSyncOpsCallBack);
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVModifyCompleteSyncOpsBW(IMG_UINT32							ui32BridgeID,
+				      PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS		*psModifySyncOpsIN,
+					  PVRSRV_BRIDGE_RETURN							*psModifySyncOpsOUT,
+					  PVRSRV_PER_PROCESS_DATA						*psPerProc)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS);
+
+	psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+													(IMG_VOID**)&psKernelSyncInfo,
+													psModifySyncOpsIN->hKernelSyncInfo,
+													PVRSRV_HANDLE_TYPE_SYNC_INFO);
+	if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyCompleteSyncOpsBW: PVRSRVLookupHandle failed"));
+		return 0;
+	}
+
+	if(psKernelSyncInfo->hResItem == IMG_NULL)
+	{
+
+		psModifySyncOpsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+
+
+
+
+
+
+
+
+
+
+	eError = ResManFreeResByPtr(psKernelSyncInfo->hResItem);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyCompleteSyncOpsBW: ResManFreeResByPtr failed"));
+		return 0;
+	}
+
+	psKernelSyncInfo->hResItem = IMG_NULL;
+
+	return 0;
+}
+
+
+PVRSRV_ERROR
+CommonBridgeInit(IMG_VOID)
+{
+	IMG_UINT32 i;
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DEVICES, PVRSRVEnumerateDevicesBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO, PVRSRVAcquireDeviceDataBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_DEVICEINFO, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT, PVRSRVCreateDeviceMemContextBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT, PVRSRVDestroyDeviceMemContextBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO, PVRSRVGetDeviceMemHeapInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ALLOC_DEVICEMEM, PVRSRVAllocDeviceMemBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_DEVICEMEM, PVRSRVFreeDeviceMemBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GETFREE_DEVICEMEM, PVRSRVGetFreeDeviceMemBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_COMMANDQUEUE, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_COMMANDQUEUE, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA, PVRMMapOSMemHandleToMMapDataBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CONNECT_SERVICES, PVRSRVConnectBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DISCONNECT_SERVICES, PVRSRVDisconnectBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_WRAP_DEVICE_MEM, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DEVICEMEMINFO, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RESERVE_DEV_VIRTMEM	, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_DEV_VIRTMEM, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_EXT_MEMORY, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_EXT_MEMORY, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DEV_MEMORY, PVRSRVMapDeviceMemoryBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_DEV_MEMORY, PVRSRVUnmapDeviceMemoryBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY, PVRSRVMapDeviceClassMemoryBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY, PVRSRVUnmapDeviceClassMemoryBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_EXPORT_DEVICEMEM, PVRSRVExportDeviceMemBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_MMAP_DATA, PVRMMapReleaseMMapDataBW);
+
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_REGISTER_SIM_PROCESS, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS, DummyBW);
+
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MAPPHYSTOUSERSPACE, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP, DummyBW);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_FB_STATS, DummyBW);
+
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_MISC_INFO, PVRSRVGetMiscInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_MISC_INFO, DummyBW);
+
+
+#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
+	SetDispatchTableEntry(PVRSRV_BRIDGE_INIT_3D_OVL_BLT_RES, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DEINIT_3D_OVL_BLT_RES, DummyBW);
+#endif
+
+
+
+#if defined(PDUMP)
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_INIT, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_MEMPOL, PDumpMemPolBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPMEM, PDumpMemBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_REG, PDumpRegWithFlagsBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_REGPOL, PDumpRegPolBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_COMMENT, PDumpCommentBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_SETFRAME, PDumpSetFrameBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_ISCAPTURING, PDumpIsCaptureFrameBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPBITMAP, PDumpBitmapBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPREADREG, PDumpReadRegBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_SYNCPOL, PDumpSyncPolBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPSYNC, PDumpSyncDumpBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DRIVERINFO, PDumpDriverInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_PDREG, PDumpPDRegBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR, PDumpPDDevPAddrBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ, PDumpCycleCountRegReadBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_STARTINITPHASE, PDumpStartInitPhaseBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_STOPINITPHASE, PDumpStopInitPhaseBW);
+#endif
+
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_OEMJTABLE, DummyBW);
+
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_CLASS, PVRSRVEnumerateDCBW);
+
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE, PVRSRVOpenDCDeviceBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE, PVRSRVCloseDCDeviceBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS, PVRSRVEnumDCFormatsBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS, PVRSRVEnumDCDimsBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER, PVRSRVGetDCSystemBufferBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_INFO, PVRSRVGetDCInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN, PVRSRVCreateDCSwapChainBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN, PVRSRVDestroyDCSwapChainBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT, PVRSRVSetDCDstRectBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT, PVRSRVSetDCSrcRectBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY, PVRSRVSetDCDstColourKeyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY, PVRSRVSetDCSrcColourKeyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS, PVRSRVGetDCBuffersBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER, PVRSRVSwapToDCBufferBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM, PVRSRVSwapToDCSystemBW);
+
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE, PVRSRVOpenBCDeviceBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE, PVRSRVCloseBCDeviceBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO, PVRSRVGetBCInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER, PVRSRVGetBCBufferBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER_ID_FROM_TAG, PVRSRVGetBCBufferIdFromTagBW);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_WRAP_EXT_MEMORY, PVRSRVWrapExtMemoryBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY, PVRSRVUnwrapExtMemoryBW);
+
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM, PVRSRVAllocSharedSysMemoryBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM, PVRSRVFreeSharedSysMemoryBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_MEMINFO_MEM, PVRSRVMapMemInfoMemBW);
+
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GETMMU_PD_DEVPADDR, MMU_GetPDDevPAddrBW);
+
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_INITSRV_CONNECT,	PVRSRVInitSrvConnectBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_INITSRV_DISCONNECT, PVRSRVInitSrvDisconnectBW);
+
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_WAIT,	PVRSRVEventObjectWaitBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_OPEN,	PVRSRVEventObjectOpenBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE, PVRSRVEventObjectCloseBW);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS, PVRSRVModifyPendingSyncOpsBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS, PVRSRVModifyCompleteSyncOpsBW);
+
+#if defined (SUPPORT_SGX)
+	SetSGXDispatchTableEntry();
+#endif
+#if defined (SUPPORT_VGX)
+	SetVGXDispatchTableEntry();
+#endif
+#if defined (SUPPORT_MSVDX)
+	SetMSVDXDispatchTableEntry();
+#endif
+
+
+
+
+	for(i=0;i<BRIDGE_DISPATCH_TABLE_ENTRY_COUNT;i++)
+	{
+		if(!g_BridgeDispatchTable[i].pfFunction)
+		{
+			g_BridgeDispatchTable[i].pfFunction = DummyBW;
+#if defined(DEBUG_BRIDGE_KM)
+			g_BridgeDispatchTable[i].pszIOCName = "_PVRSRV_BRIDGE_DUMMY";
+			g_BridgeDispatchTable[i].pszFunctionName = "DummyBW";
+			g_BridgeDispatchTable[i].ui32CallCount = 0;
+			g_BridgeDispatchTable[i].ui32CopyFromUserTotalBytes = 0;
+			g_BridgeDispatchTable[i].ui32CopyToUserTotalBytes = 0;
+#endif
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+
+IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+					  PVRSRV_BRIDGE_PACKAGE   * psBridgePackageKM)
+{
+
+	IMG_VOID   * psBridgeIn;
+	IMG_VOID   * psBridgeOut;
+	BridgeWrapperFunction pfBridgeHandler;
+	IMG_UINT32   ui32BridgeID = psBridgePackageKM->ui32BridgeID;
+	IMG_INT      err          = -EFAULT;
+
+#if defined(DEBUG_TRACE_BRIDGE_KM)
+	PVR_DPF((PVR_DBG_ERROR, "%s: %s",
+			 __FUNCTION__,
+			 g_BridgeDispatchTable[ui32BridgeID].pszIOCName));
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+	g_BridgeDispatchTable[ui32BridgeID].ui32CallCount++;
+	g_BridgeGlobalStats.ui32IOCTLCount++;
+#endif
+
+	if(!psPerProc->bInitProcess)
+	{
+		if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
+		{
+			if(!PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Initialisation failed.  Driver unusable.",
+						 __FUNCTION__));
+				goto return_fault;
+			}
+		}
+		else
+		{
+			if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING))
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Initialisation is in progress",
+						 __FUNCTION__));
+				goto return_fault;
+			}
+			else
+			{
+
+				switch(ui32BridgeID)
+				{
+					case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_CONNECT_SERVICES):
+					case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_DISCONNECT_SERVICES):
+					case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_INITSRV_CONNECT):
+					case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_INITSRV_DISCONNECT):
+						break;
+					default:
+						PVR_DPF((PVR_DBG_ERROR, "%s: Driver initialisation not completed yet.",
+								 __FUNCTION__));
+						goto return_fault;
+				}
+			}
+		}
+	}
+
+
+
+#if defined(__linux__)
+	{
+
+		SYS_DATA *psSysData;
+
+		SysAcquireData(&psSysData);
+
+
+		psBridgeIn = ((ENV_DATA *)psSysData->pvEnvSpecificData)->pvBridgeData;
+		psBridgeOut = (IMG_PVOID)((IMG_PBYTE)psBridgeIn + PVRSRV_MAX_BRIDGE_IN_SIZE);
+
+		if(psBridgePackageKM->ui32InBufferSize > 0)
+		{
+			if(!OSAccessOK(PVR_VERIFY_READ,
+							psBridgePackageKM->pvParamIn,
+							psBridgePackageKM->ui32InBufferSize))
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Invalid pvParamIn pointer", __FUNCTION__));
+			}
+
+			if(CopyFromUserWrapper(psPerProc,
+					               ui32BridgeID,
+								   psBridgeIn,
+								   psBridgePackageKM->pvParamIn,
+								   psBridgePackageKM->ui32InBufferSize)
+			  != PVRSRV_OK)
+			{
+				goto return_fault;
+			}
+		}
+	}
+#else
+	psBridgeIn  = psBridgePackageKM->pvParamIn;
+	psBridgeOut = psBridgePackageKM->pvParamOut;
+#endif
+
+	if(ui32BridgeID >= (BRIDGE_DISPATCH_TABLE_ENTRY_COUNT))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: ui32BridgeID = %d is out if range!",
+				 __FUNCTION__, ui32BridgeID));
+		goto return_fault;
+	}
+	pfBridgeHandler =
+		(BridgeWrapperFunction)g_BridgeDispatchTable[ui32BridgeID].pfFunction;
+	err = pfBridgeHandler(ui32BridgeID,
+						  psBridgeIn,
+						  psBridgeOut,
+						  psPerProc);
+	if(err < 0)
+	{
+		goto return_fault;
+	}
+
+
+#if defined(__linux__)
+
+	if(CopyToUserWrapper(psPerProc,
+						 ui32BridgeID,
+						 psBridgePackageKM->pvParamOut,
+						 psBridgeOut,
+						 psBridgePackageKM->ui32OutBufferSize)
+	   != PVRSRV_OK)
+	{
+		goto return_fault;
+	}
+#endif
+
+	err = 0;
+return_fault:
+	ReleaseHandleBatch(psPerProc);
+	return err;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_pvr_bridge.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_pvr_bridge.h
new file mode 100644
index 0000000..9d03a24
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_pvr_bridge.h
@@ -0,0 +1,227 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __BRIDGED_PVR_BRIDGE_H__
+#define __BRIDGED_PVR_BRIDGE_H__
+
+#include "pvr_bridge.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__)
+#define PVRSRV_GET_BRIDGE_ID(X)	_IOC_NR(X)
+#else
+#define PVRSRV_GET_BRIDGE_ID(X)	(X - PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST))
+#endif
+
+#ifndef ENOMEM
+#define ENOMEM	12
+#endif
+#ifndef EFAULT
+#define EFAULT	14
+#endif
+#ifndef ENOTTY
+#define ENOTTY	25
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_ERROR
+CopyFromUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+					IMG_UINT32 ui32BridgeID,
+					IMG_VOID *pvDest,
+					IMG_VOID *pvSrc,
+					IMG_UINT32 ui32Size);
+PVRSRV_ERROR
+CopyToUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+				  IMG_UINT32 ui32BridgeID,
+				  IMG_VOID *pvDest,
+				  IMG_VOID *pvSrc,
+				  IMG_UINT32 ui32Size);
+#else
+#define CopyFromUserWrapper(pProcData, ui32BridgeID, pvDest, pvSrc, ui32Size) \
+	OSCopyFromUser(pProcData, pvDest, pvSrc, ui32Size)
+#define CopyToUserWrapper(pProcData, ui32BridgeID, pvDest, pvSrc, ui32Size) \
+	OSCopyToUser(pProcData, pvDest, pvSrc, ui32Size)
+#endif
+
+
+#define ASSIGN_AND_RETURN_ON_ERROR(error, src, res)		\
+	do							\
+	{							\
+		(error) = (src);				\
+		if ((error) != PVRSRV_OK) 			\
+		{						\
+			return (res);				\
+		}						\
+	} while (error != PVRSRV_OK)
+
+#define ASSIGN_AND_EXIT_ON_ERROR(error, src)		\
+	ASSIGN_AND_RETURN_ON_ERROR(error, src, 0)
+
+#if defined (PVR_SECURE_HANDLES)
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NewHandleBatch)
+#endif
+static INLINE PVRSRV_ERROR
+NewHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc,
+					IMG_UINT32 ui32BatchSize)
+{
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(!psPerProc->bHandlesBatched);
+
+	eError = PVRSRVNewHandleBatch(psPerProc->psHandleBase, ui32BatchSize);
+
+	if (eError == PVRSRV_OK)
+	{
+		psPerProc->bHandlesBatched = IMG_TRUE;
+	}
+
+	return eError;
+}
+
+#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize)	\
+	ASSIGN_AND_EXIT_ON_ERROR(error, NewHandleBatch(psPerProc, ui32BatchSize))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(CommitHandleBatch)
+#endif
+static INLINE PVRSRV_ERROR
+CommitHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVR_ASSERT(psPerProc->bHandlesBatched);
+
+	psPerProc->bHandlesBatched = IMG_FALSE;
+
+	return PVRSRVCommitHandleBatch(psPerProc->psHandleBase);
+}
+
+
+#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc) 			\
+	ASSIGN_AND_EXIT_ON_ERROR(error, CommitHandleBatch(psPerProc))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ReleaseHandleBatch)
+#endif
+static INLINE IMG_VOID
+ReleaseHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	if (psPerProc->bHandlesBatched)
+	{
+		psPerProc->bHandlesBatched = IMG_FALSE;
+
+		PVRSRVReleaseHandleBatch(psPerProc->psHandleBase);
+	}
+}
+#else
+#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize)
+#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc)
+#define ReleaseHandleBatch(psPerProc)
+#endif
+
+IMG_INT
+DummyBW(IMG_UINT32 ui32BridgeID,
+		IMG_VOID *psBridgeIn,
+		IMG_VOID *psBridgeOut,
+		PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+typedef IMG_INT (*BridgeWrapperFunction)(IMG_UINT32 ui32BridgeID,
+									 IMG_VOID *psBridgeIn,
+									 IMG_VOID *psBridgeOut,
+									 PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+typedef struct _PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY
+{
+	BridgeWrapperFunction pfFunction;
+#if defined(DEBUG_BRIDGE_KM)
+	const IMG_CHAR *pszIOCName;
+	const IMG_CHAR *pszFunctionName;
+	IMG_UINT32 ui32CallCount;
+	IMG_UINT32 ui32CopyFromUserTotalBytes;
+	IMG_UINT32 ui32CopyToUserTotalBytes;
+#endif
+}PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY;
+
+#if defined(SUPPORT_VGX) || defined(SUPPORT_MSVDX)
+	#if defined(SUPPORT_VGX)
+		#define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_VGX_CMD+1)
+		#define PVRSRV_BRIDGE_LAST_DEVICE_CMD	   PVRSRV_BRIDGE_LAST_VGX_CMD
+	#else
+		#define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_MSVDX_CMD+1)
+		#define PVRSRV_BRIDGE_LAST_DEVICE_CMD	   PVRSRV_BRIDGE_LAST_MSVDX_CMD
+	#endif
+#else
+	#if defined(SUPPORT_SGX)
+		#define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_SGX_CMD+1)
+		#define PVRSRV_BRIDGE_LAST_DEVICE_CMD	   PVRSRV_BRIDGE_LAST_SGX_CMD
+	#else
+		#define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD+1)
+		#define PVRSRV_BRIDGE_LAST_DEVICE_CMD	   PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD
+	#endif
+#endif
+
+extern PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+IMG_VOID
+_SetDispatchTableEntry(IMG_UINT32 ui32Index,
+					   const IMG_CHAR *pszIOCName,
+					   BridgeWrapperFunction pfFunction,
+					   const IMG_CHAR *pszFunctionName);
+
+
+#define SetDispatchTableEntry(ui32Index, pfFunction) \
+	_SetDispatchTableEntry(PVRSRV_GET_BRIDGE_ID(ui32Index), #ui32Index, (BridgeWrapperFunction)pfFunction, #pfFunction)
+
+#define DISPATCH_TABLE_GAP_THRESHOLD 5
+
+#if defined(DEBUG)
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_ASSERT(X == PVRSRV_GET_BRIDGE_ID(Y))
+#else
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_UNREFERENCED_PARAMETER(X)
+#endif
+
+
+#if defined(DEBUG_BRIDGE_KM)
+typedef struct _PVRSRV_BRIDGE_GLOBAL_STATS
+{
+	IMG_UINT32 ui32IOCTLCount;
+	IMG_UINT32 ui32TotalCopyFromUserBytes;
+	IMG_UINT32 ui32TotalCopyToUserBytes;
+}PVRSRV_BRIDGE_GLOBAL_STATS;
+
+extern PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+
+PVRSRV_ERROR CommonBridgeInit(IMG_VOID);
+
+IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+					  PVRSRV_BRIDGE_PACKAGE   * psBridgePackageKM);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_support.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_support.c
new file mode 100644
index 0000000..b82231a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_support.c
@@ -0,0 +1,81 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "img_defs.h"
+#include "servicesint.h"
+#include "bridged_support.h"
+
+
+PVRSRV_ERROR
+PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psHandleBase, IMG_HANDLE *phOSMemHandle, IMG_HANDLE hMHandle)
+{
+	IMG_HANDLE hMHandleInt;
+	PVRSRV_HANDLE_TYPE eHandleType;
+	PVRSRV_ERROR eError;
+
+
+	eError = PVRSRVLookupHandleAnyType(psHandleBase, &hMHandleInt,
+							  &eHandleType,
+							  hMHandle);
+	if(eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	switch(eHandleType)
+	{
+#if defined(PVR_SECURE_HANDLES)
+		case PVRSRV_HANDLE_TYPE_MEM_INFO:
+		case PVRSRV_HANDLE_TYPE_MEM_INFO_REF:
+		case PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO:
+		{
+			PVRSRV_KERNEL_MEM_INFO *psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)hMHandleInt;
+
+			*phOSMemHandle = psMemInfo->sMemBlk.hOSMemHandle;
+
+			break;
+		}
+		case PVRSRV_HANDLE_TYPE_SYNC_INFO:
+		{
+			PVRSRV_KERNEL_SYNC_INFO *psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)hMHandleInt;
+			PVRSRV_KERNEL_MEM_INFO *psMemInfo = psSyncInfo->psSyncDataMemInfoKM;
+
+			*phOSMemHandle = psMemInfo->sMemBlk.hOSMemHandle;
+
+			break;
+		}
+		case  PVRSRV_HANDLE_TYPE_SOC_TIMER:
+		{
+			*phOSMemHandle = (IMG_VOID *)hMHandleInt;
+			break;
+		}
+#else
+		case  PVRSRV_HANDLE_TYPE_NONE:
+			*phOSMemHandle = (IMG_VOID *)hMHandleInt;
+			break;
+#endif
+		default:
+			return PVRSRV_ERROR_BAD_MAPPING;
+	}
+
+	return PVRSRV_OK;
+}
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_support.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_support.h
new file mode 100644
index 0000000..b5c2d15
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/bridged_support.h
@@ -0,0 +1,39 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __BRIDGED_SUPPORT_H__
+#define __BRIDGED_SUPPORT_H__
+
+#include "handle.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+PVRSRV_ERROR PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phOSMemHandle, IMG_HANDLE hMHandle);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c
new file mode 100644
index 0000000..de4e697
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c
@@ -0,0 +1,2510 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+
+
+#include <stddef.h>
+
+#include "img_defs.h"
+
+#if defined(SUPPORT_SGX)
+
+#include "services.h"
+#include "pvr_debug.h"
+#include "pvr_bridge.h"
+#include "sgx_bridge.h"
+#include "perproc.h"
+#include "power.h"
+#include "pvr_bridge_km.h"
+#include "sgx_bridge_km.h"
+
+#if defined(SUPPORT_MSVDX)
+	#include "msvdx_bridge.h"
+#endif
+
+#include "bridged_pvr_bridge.h"
+#include "bridged_sgx_bridge.h"
+#include "sgxutils.h"
+#include "pdump_km.h"
+
+static IMG_INT
+SGXGetClientInfoBW(IMG_UINT32 ui32BridgeID,
+				   PVRSRV_BRIDGE_IN_GETCLIENTINFO *psGetClientInfoIN,
+				   PVRSRV_BRIDGE_OUT_GETCLIENTINFO *psGetClientInfoOUT,
+				   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_GETCLIENTINFO);
+
+	psGetClientInfoOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psGetClientInfoIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psGetClientInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetClientInfoOUT->eError =
+		SGXGetClientInfoKM(hDevCookieInt,
+						   &psGetClientInfoOUT->sClientInfo);
+	return 0;
+}
+
+static IMG_INT
+SGXReleaseClientInfoBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_RELEASECLIENTINFO *psReleaseClientInfoIN,
+					   PVRSRV_BRIDGE_RETURN *psRetOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_SGXDEV_INFO *psDevInfo;
+	IMG_HANDLE hDevCookieInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psReleaseClientInfoIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+	PVR_ASSERT(psDevInfo->ui32ClientRefCount > 0);
+
+	psDevInfo->ui32ClientRefCount--;
+
+	psRetOUT->eError = PVRSRV_OK;
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXGetInternalDevInfoBW(IMG_UINT32 ui32BridgeID,
+						PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO *psSGXGetInternalDevInfoIN,
+						PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO *psSGXGetInternalDevInfoOUT,
+						PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO);
+
+	psSGXGetInternalDevInfoOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psSGXGetInternalDevInfoIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psSGXGetInternalDevInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psSGXGetInternalDevInfoOUT->eError =
+		SGXGetInternalDevInfoKM(hDevCookieInt,
+								&psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo);
+
+
+	psSGXGetInternalDevInfoOUT->eError =
+		PVRSRVAllocHandle(psPerProc->psHandleBase,
+						  &psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
+						  psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
+						  PVRSRV_HANDLE_TYPE_MEM_INFO,
+						  PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXDoKickBW(IMG_UINT32 ui32BridgeID,
+			PVRSRV_BRIDGE_IN_DOKICK *psDoKickIN,
+			PVRSRV_BRIDGE_RETURN *psRetOUT,
+			PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_UINT32 i;
+	IMG_INT ret = 0;
+	IMG_UINT32 ui32NumDstSyncs;
+	IMG_HANDLE *phKernelSyncInfoHandles = IMG_NULL;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DOKICK);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psDoKickIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &psDoKickIN->sCCBKick.hCCBKernelMemInfo,
+						   psDoKickIN->sCCBKick.hCCBKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	if(psDoKickIN->sCCBKick.hTA3DSyncInfo != IMG_NULL)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.hTA3DSyncInfo,
+							   psDoKickIN->sCCBKick.hTA3DSyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if(psDoKickIN->sCCBKick.hTASyncInfo != IMG_NULL)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.hTASyncInfo,
+							   psDoKickIN->sCCBKick.hTASyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if(psDoKickIN->sCCBKick.h3DSyncInfo != IMG_NULL)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.h3DSyncInfo,
+							   psDoKickIN->sCCBKick.h3DSyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+	if (psDoKickIN->sCCBKick.ui32NumTASrcSyncs > SGX_MAX_TA_SRC_SYNCS)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+
+	for(i=0; i<psDoKickIN->sCCBKick.ui32NumTASrcSyncs; i++)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.ahTASrcKernelSyncInfo[i],
+							   psDoKickIN->sCCBKick.ahTASrcKernelSyncInfo[i],
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if (psDoKickIN->sCCBKick.ui32NumTADstSyncs > SGX_MAX_TA_DST_SYNCS)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+
+	for(i=0; i<psDoKickIN->sCCBKick.ui32NumTADstSyncs; i++)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.ahTADstKernelSyncInfo[i],
+							   psDoKickIN->sCCBKick.ahTADstKernelSyncInfo[i],
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if (psDoKickIN->sCCBKick.ui32Num3DSrcSyncs > SGX_MAX_3D_SRC_SYNCS)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+
+	for(i=0; i<psDoKickIN->sCCBKick.ui32Num3DSrcSyncs; i++)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.ah3DSrcKernelSyncInfo[i],
+							   psDoKickIN->sCCBKick.ah3DSrcKernelSyncInfo[i],
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+#else
+
+	if (psDoKickIN->sCCBKick.ui32NumSrcSyncs > SGX_MAX_SRC_SYNCS)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+	for(i=0; i<psDoKickIN->sCCBKick.ui32NumSrcSyncs; i++)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.ahSrcKernelSyncInfo[i],
+							   psDoKickIN->sCCBKick.ahSrcKernelSyncInfo[i],
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+#endif
+
+	if (psDoKickIN->sCCBKick.ui32NumTAStatusVals > SGX_MAX_TA_STATUS_VALS)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+	for (i = 0; i < psDoKickIN->sCCBKick.ui32NumTAStatusVals; i++)
+	{
+		psRetOUT->eError =
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.asTAStatusUpdate[i].hKernelMemInfo,
+							   psDoKickIN->sCCBKick.asTAStatusUpdate[i].hKernelMemInfo,
+							   PVRSRV_HANDLE_TYPE_MEM_INFO);
+#else
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i],
+							   psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i],
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+#endif
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if (psDoKickIN->sCCBKick.ui32Num3DStatusVals > SGX_MAX_3D_STATUS_VALS)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+	for(i = 0; i < psDoKickIN->sCCBKick.ui32Num3DStatusVals; i++)
+	{
+		psRetOUT->eError =
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.as3DStatusUpdate[i].hKernelMemInfo,
+							   psDoKickIN->sCCBKick.as3DStatusUpdate[i].hKernelMemInfo,
+							   PVRSRV_HANDLE_TYPE_MEM_INFO);
+#else
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i],
+							   psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i],
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+#endif
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	ui32NumDstSyncs = psDoKickIN->sCCBKick.ui32NumDstSyncObjects;
+
+	if(ui32NumDstSyncs > 0)
+	{
+		if(!OSAccessOK(PVR_VERIFY_READ,
+						psDoKickIN->sCCBKick.pahDstSyncHandles,
+						ui32NumDstSyncs * sizeof(IMG_HANDLE)))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: SGXDoKickBW:"
+					" Invalid pasDstSyncHandles pointer", __FUNCTION__));
+			return -EFAULT;
+		}
+
+		psRetOUT->eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+										ui32NumDstSyncs * sizeof(IMG_HANDLE),
+										(IMG_VOID **)&phKernelSyncInfoHandles,
+										0,
+										"Array of Synchronization Info Handles");
+		if (psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+
+		if(CopyFromUserWrapper(psPerProc,
+							ui32BridgeID,
+							phKernelSyncInfoHandles,
+							psDoKickIN->sCCBKick.pahDstSyncHandles,
+							ui32NumDstSyncs * sizeof(IMG_HANDLE)) != PVRSRV_OK)
+		{
+			ret = -EFAULT;
+			goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+		}
+
+
+		psDoKickIN->sCCBKick.pahDstSyncHandles = phKernelSyncInfoHandles;
+
+		for( i = 0; i < ui32NumDstSyncs; i++)
+		{
+			psRetOUT->eError =
+				PVRSRVLookupHandle(psPerProc->psHandleBase,
+									&psDoKickIN->sCCBKick.pahDstSyncHandles[i],
+									psDoKickIN->sCCBKick.pahDstSyncHandles[i],
+									PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+			if(psRetOUT->eError != PVRSRV_OK)
+			{
+				goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+			}
+
+		}
+
+		psRetOUT->eError =
+					PVRSRVLookupHandle(psPerProc->psHandleBase,
+									   &psDoKickIN->sCCBKick.hKernelHWSyncListMemInfo,
+									   psDoKickIN->sCCBKick.hKernelHWSyncListMemInfo,
+									   PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+		}
+	}
+
+	psRetOUT->eError =
+		SGXDoKickKM(hDevCookieInt,
+					&psDoKickIN->sCCBKick);
+
+PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT:
+
+	if(phKernelSyncInfoHandles)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  ui32NumDstSyncs * sizeof(IMG_HANDLE),
+				  (IMG_VOID *)phKernelSyncInfoHandles,
+				  0);
+
+	}
+	return ret;
+}
+
+
+static IMG_INT
+SGXScheduleProcessQueuesBW(IMG_UINT32 ui32BridgeID,
+			PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES *psScheduleProcQIN,
+			PVRSRV_BRIDGE_RETURN *psRetOUT,
+			PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psScheduleProcQIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = SGXScheduleProcessQueuesKM(hDevCookieInt);
+
+	return 0;
+}
+
+
+#if defined(TRANSFER_QUEUE)
+static IMG_INT
+SGXSubmitTransferBW(IMG_UINT32 ui32BridgeID,
+			PVRSRV_BRIDGE_IN_SUBMITTRANSFER *psSubmitTransferIN,
+			PVRSRV_BRIDGE_RETURN *psRetOUT,
+			PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	PVRSRV_TRANSFER_SGX_KICK *psKick;
+	IMG_UINT32 i;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SUBMITTRANSFER);
+	PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+	psKick = &psSubmitTransferIN->sKick;
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSubmitTransferIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &psKick->hCCBMemInfo,
+						   psKick->hCCBMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	if (psKick->hTASyncInfo != IMG_NULL)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psKick->hTASyncInfo,
+							   psKick->hTASyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if (psKick->h3DSyncInfo != IMG_NULL)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psKick->h3DSyncInfo,
+							   psKick->h3DSyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if (psKick->ui32NumSrcSync > SGX_MAX_TRANSFER_SYNC_OPS)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+	for (i = 0; i < psKick->ui32NumSrcSync; i++)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psKick->ahSrcSyncInfo[i],
+							   psKick->ahSrcSyncInfo[i],
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if (psKick->ui32NumDstSync > SGX_MAX_TRANSFER_SYNC_OPS)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+	for (i = 0; i < psKick->ui32NumDstSync; i++)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psKick->ahDstSyncInfo[i],
+							   psKick->ahDstSyncInfo[i],
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	psRetOUT->eError = SGXSubmitTransferKM(hDevCookieInt, psKick);
+
+	return 0;
+}
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+static IMG_INT
+SGXSubmit2DBW(IMG_UINT32 ui32BridgeID,
+			PVRSRV_BRIDGE_IN_SUBMIT2D *psSubmit2DIN,
+			PVRSRV_BRIDGE_RETURN *psRetOUT,
+			PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	PVRSRV_2D_SGX_KICK *psKick;
+	IMG_UINT32 i;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SUBMIT2D);
+	PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSubmit2DIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psKick = &psSubmit2DIN->sKick;
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &psKick->hCCBMemInfo,
+						   psKick->hCCBMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	if (psKick->hTASyncInfo != IMG_NULL)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psKick->hTASyncInfo,
+							   psKick->hTASyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if (psKick->h3DSyncInfo != IMG_NULL)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psKick->h3DSyncInfo,
+							   psKick->h3DSyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if (psKick->ui32NumSrcSync > SGX_MAX_2D_SRC_SYNC_OPS)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+	for (i = 0; i < psKick->ui32NumSrcSync; i++)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psKick->ahSrcSyncInfo[i],
+							   psKick->ahSrcSyncInfo[i],
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if (psKick->hDstSyncInfo != IMG_NULL)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psKick->hDstSyncInfo,
+							   psKick->hDstSyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	psRetOUT->eError =
+		SGXSubmit2DKM(hDevCookieInt, psKick);
+
+	return 0;
+}
+#endif
+#endif
+
+
+static IMG_INT
+SGXGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
+				 PVRSRV_BRIDGE_IN_SGXGETMISCINFO *psSGXGetMiscInfoIN,
+				 PVRSRV_BRIDGE_RETURN *psRetOUT,
+				 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hDevMemContextInt = 0;
+	PVRSRV_SGXDEV_INFO *psDevInfo;
+	SGX_MISC_INFO        sMiscInfo;
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+							PVRSRV_BRIDGE_SGX_GETMISCINFO);
+
+	psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+							&hDevCookieInt,
+							psSGXGetMiscInfoIN->hDevCookie,
+							PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+
+	if (psSGXGetMiscInfoIN->psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMREAD)
+	{
+		psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+								&hDevMemContextInt,
+								psSGXGetMiscInfoIN->psMiscInfo->hDevMemContext,
+								PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+#endif
+
+	psDeviceNode = hDevCookieInt;
+	PVR_ASSERT(psDeviceNode != IMG_NULL);
+	if (psDeviceNode == IMG_NULL)
+	{
+		return -EFAULT;
+	}
+
+	psDevInfo = psDeviceNode->pvDevice;
+
+
+	psRetOUT->eError = CopyFromUserWrapper(psPerProc,
+			                               ui32BridgeID,
+			                               &sMiscInfo,
+			                               psSGXGetMiscInfoIN->psMiscInfo,
+			                               sizeof(SGX_MISC_INFO));
+	if (psRetOUT->eError != PVRSRV_OK)
+	{
+		return -EFAULT;
+	}
+
+#ifdef SUPPORT_SGX_HWPERF
+	if (sMiscInfo.eRequest == SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB)
+	{
+
+		IMG_VOID           * pAllocated;
+		IMG_HANDLE           hAllocatedHandle;
+		IMG_VOID           * psTmpUserData;
+		IMG_UINT32           allocatedSize;
+
+		allocatedSize = (IMG_UINT32)(sMiscInfo.uData.sRetrieveCB.ui32ArraySize * sizeof(PVRSRV_SGX_HWPERF_CBDATA));
+
+		ASSIGN_AND_EXIT_ON_ERROR(psRetOUT->eError,
+		                    OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+		                    allocatedSize,
+		                    &pAllocated,
+		                    &hAllocatedHandle,
+							"Array of Hardware Performance Circular Buffer Data"));
+
+
+		psTmpUserData = sMiscInfo.uData.sRetrieveCB.psHWPerfData;
+		sMiscInfo.uData.sRetrieveCB.psHWPerfData = pAllocated;
+
+		psRetOUT->eError = SGXGetMiscInfoKM(psDevInfo, &sMiscInfo, psDeviceNode, 0);
+		if (psRetOUT->eError != PVRSRV_OK)
+		{
+			OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+					  allocatedSize,
+					  pAllocated,
+					  hAllocatedHandle);
+
+			return 0;
+		}
+
+
+		psRetOUT->eError = CopyToUserWrapper(psPerProc,
+					                         ui32BridgeID,
+					                         psTmpUserData,
+					                         sMiscInfo.uData.sRetrieveCB.psHWPerfData,
+					                         allocatedSize);
+
+		sMiscInfo.uData.sRetrieveCB.psHWPerfData = psTmpUserData;
+
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  allocatedSize,
+				  pAllocated,
+			      hAllocatedHandle);
+
+		if (psRetOUT->eError != PVRSRV_OK)
+		{
+			return -EFAULT;
+		}
+	}
+	else
+#endif
+	{
+		psRetOUT->eError = SGXGetMiscInfoKM(psDevInfo, &sMiscInfo, psDeviceNode, hDevMemContextInt);
+
+		if (psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+
+	psRetOUT->eError = CopyToUserWrapper(psPerProc,
+		                             ui32BridgeID,
+		                             psSGXGetMiscInfoIN->psMiscInfo,
+		                             &sMiscInfo,
+		                             sizeof(SGX_MISC_INFO));
+	if (psRetOUT->eError != PVRSRV_OK)
+	{
+		return -EFAULT;
+	}
+	return 0;
+}
+
+
+#if defined(SUPPORT_SGX_HWPERF)
+static IMG_INT
+SGXReadDiffCountersBW(IMG_UINT32									ui32BridgeID,
+						PVRSRV_BRIDGE_IN_SGX_READ_DIFF_COUNTERS		*psSGXReadDiffCountersIN,
+						PVRSRV_BRIDGE_OUT_SGX_READ_DIFF_COUNTERS	*psSGXReadDiffCountersOUT,
+						PVRSRV_PER_PROCESS_DATA						*psPerProc)
+{
+	IMG_HANDLE			hDevCookieInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_READ_DIFF_COUNTERS);
+
+	psSGXReadDiffCountersOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+							&hDevCookieInt,
+							psSGXReadDiffCountersIN->hDevCookie,
+							PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psSGXReadDiffCountersOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psSGXReadDiffCountersOUT->eError = SGXReadDiffCountersKM(hDevCookieInt,
+							psSGXReadDiffCountersIN->ui32Reg,
+							&psSGXReadDiffCountersOUT->ui32Old,
+							psSGXReadDiffCountersIN->bNew,
+							psSGXReadDiffCountersIN->ui32New,
+							psSGXReadDiffCountersIN->ui32NewReset,
+							psSGXReadDiffCountersIN->ui32CountersReg,
+							psSGXReadDiffCountersIN->ui32Reg2,
+							&psSGXReadDiffCountersOUT->bActive,
+							&psSGXReadDiffCountersOUT->sDiffs);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXReadHWPerfCBBW(IMG_UINT32							ui32BridgeID,
+				  PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB	*psSGXReadHWPerfCBIN,
+				  PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB	*psSGXReadHWPerfCBOUT,
+				  PVRSRV_PER_PROCESS_DATA				*psPerProc)
+{
+	IMG_HANDLE					hDevCookieInt;
+	PVRSRV_SGX_HWPERF_CB_ENTRY	*psAllocated;
+	IMG_HANDLE					hAllocatedHandle;
+	IMG_UINT32					ui32AllocatedSize;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_READ_HWPERF_CB);
+
+	psSGXReadHWPerfCBOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+							&hDevCookieInt,
+							psSGXReadHWPerfCBIN->hDevCookie,
+							PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psSGXReadHWPerfCBOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	ui32AllocatedSize = psSGXReadHWPerfCBIN->ui32ArraySize *
+							sizeof(psSGXReadHWPerfCBIN->psHWPerfCBData[0]);
+	ASSIGN_AND_EXIT_ON_ERROR(psSGXReadHWPerfCBOUT->eError,
+	                    OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+	                    ui32AllocatedSize,
+	                    (IMG_VOID **)&psAllocated,
+	                    &hAllocatedHandle,
+						"Array of Hardware Performance Circular Buffer Data"));
+
+	psSGXReadHWPerfCBOUT->eError = SGXReadHWPerfCBKM(hDevCookieInt,
+													 psSGXReadHWPerfCBIN->ui32ArraySize,
+													 psAllocated,
+													 &psSGXReadHWPerfCBOUT->ui32DataCount,
+													 &psSGXReadHWPerfCBOUT->ui32ClockSpeed,
+													 &psSGXReadHWPerfCBOUT->ui32HostTimeStamp);
+	if (psSGXReadHWPerfCBOUT->eError == PVRSRV_OK)
+	{
+		psSGXReadHWPerfCBOUT->eError = CopyToUserWrapper(psPerProc,
+		                                                 ui32BridgeID,
+		                                                 psSGXReadHWPerfCBIN->psHWPerfCBData,
+		                                                 psAllocated,
+		                                                 ui32AllocatedSize);
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+			  ui32AllocatedSize,
+			  psAllocated,
+			  hAllocatedHandle);
+
+
+	return 0;
+}
+#endif
+
+
+static IMG_INT
+SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
+				  PVRSRV_BRIDGE_IN_SGXDEVINITPART2 *psSGXDevInitPart2IN,
+				  PVRSRV_BRIDGE_RETURN *psRetOUT,
+				  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	PVRSRV_ERROR eError;
+	IMG_BOOL bDissociateFailed = IMG_FALSE;
+	IMG_BOOL bLookupFailed = IMG_FALSE;
+	IMG_BOOL bReleaseFailed = IMG_FALSE;
+	IMG_HANDLE hDummy;
+	IMG_UINT32 i;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DEVINITPART2);
+
+	if(!psPerProc->bInitProcess)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSGXDevInitPart2IN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SGX_FEATURE_SPM_MODE_0)
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+	for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+	{
+		IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+		if (hHandle == IMG_NULL)
+		{
+			continue;
+		}
+
+		eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &hDummy,
+							   hHandle,
+							   PVRSRV_HANDLE_TYPE_MEM_INFO);
+		bLookupFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+	}
+
+	if (bLookupFailed)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle lookup failed"));
+		psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+		return 0;
+	}
+
+
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+
+	#if defined(SGX_SUPPORT_HWPROFILING)
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SGX_FEATURE_SPM_MODE_0)
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+
+	for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+	{
+		IMG_HANDLE *phHandle = &psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+		if (*phHandle == IMG_NULL)
+			continue;
+
+		eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+							   phHandle,
+							   *phHandle,
+							   PVRSRV_HANDLE_TYPE_MEM_INFO);
+		bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+	}
+
+	if (bReleaseFailed)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle release failed"));
+		psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+
+		PVR_DBG_BREAK;
+		return 0;
+	}
+
+
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SGX_FEATURE_SPM_MODE_0)
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+	for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+	{
+		IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+		if (hHandle == IMG_NULL)
+			continue;
+
+		eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, hHandle);
+		bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+	}
+
+
+
+
+	if(bDissociateFailed)
+	{
+		PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo);
+		PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo);
+		PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo);
+		PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo);
+		PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo);
+
+		for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+		{
+			IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+			if (hHandle == IMG_NULL)
+				continue;
+
+			PVRSRVFreeDeviceMemKM(hDevCookieInt, (PVRSRV_KERNEL_MEM_INFO *)hHandle);
+
+		}
+
+		PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A dissociate failed"));
+
+		psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+
+
+		PVR_DBG_BREAK;
+		return 0;
+	}
+
+	psRetOUT->eError =
+		DevInitSGXPart2KM(psPerProc,
+						  hDevCookieInt,
+						  &psSGXDevInitPart2IN->sInitInfo);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXRegisterHWRenderContextBW(IMG_UINT32 ui32BridgeID,
+							 PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT *psSGXRegHWRenderContextIN,
+							 PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT *psSGXRegHWRenderContextOUT,
+							 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hHWRenderContextInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHWRenderContextOUT->eError, psPerProc, 1);
+
+	psSGXRegHWRenderContextOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSGXRegHWRenderContextIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psSGXRegHWRenderContextOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	hHWRenderContextInt =
+		SGXRegisterHWRenderContextKM(hDevCookieInt,
+									 &psSGXRegHWRenderContextIN->sHWRenderContextDevVAddr,
+									 psPerProc);
+
+	if (hHWRenderContextInt == IMG_NULL)
+	{
+		psSGXRegHWRenderContextOUT->eError = PVRSRV_ERROR_GENERIC;
+		return 0;
+	}
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psSGXRegHWRenderContextOUT->hHWRenderContext,
+					  hHWRenderContextInt,
+					  PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHWRenderContextOUT->eError, psPerProc);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHWRenderContextBW(IMG_UINT32 ui32BridgeID,
+							   PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT *psSGXUnregHWRenderContextIN,
+							   PVRSRV_BRIDGE_RETURN *psRetOUT,
+							   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hHWRenderContextInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hHWRenderContextInt,
+						   psSGXUnregHWRenderContextIN->hHWRenderContext,
+						   PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = SGXUnregisterHWRenderContextKM(hHWRenderContextInt);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psSGXUnregHWRenderContextIN->hHWRenderContext,
+							PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXRegisterHWTransferContextBW(IMG_UINT32 ui32BridgeID,
+							 PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT *psSGXRegHWTransferContextIN,
+							 PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT *psSGXRegHWTransferContextOUT,
+							 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hHWTransferContextInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHWTransferContextOUT->eError, psPerProc, 1);
+
+	psSGXRegHWTransferContextOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSGXRegHWTransferContextIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psSGXRegHWTransferContextOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	hHWTransferContextInt =
+		SGXRegisterHWTransferContextKM(hDevCookieInt,
+									   &psSGXRegHWTransferContextIN->sHWTransferContextDevVAddr,
+									   psPerProc);
+
+	if (hHWTransferContextInt == IMG_NULL)
+	{
+		psSGXRegHWTransferContextOUT->eError = PVRSRV_ERROR_GENERIC;
+		return 0;
+	}
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psSGXRegHWTransferContextOUT->hHWTransferContext,
+					  hHWTransferContextInt,
+					  PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHWTransferContextOUT->eError, psPerProc);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHWTransferContextBW(IMG_UINT32 ui32BridgeID,
+							   PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT *psSGXUnregHWTransferContextIN,
+							   PVRSRV_BRIDGE_RETURN *psRetOUT,
+							   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hHWTransferContextInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hHWTransferContextInt,
+						   psSGXUnregHWTransferContextIN->hHWTransferContext,
+						   PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = SGXUnregisterHWTransferContextKM(hHWTransferContextInt);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psSGXUnregHWTransferContextIN->hHWTransferContext,
+							PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT);
+
+	return 0;
+}
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+static IMG_INT
+SGXRegisterHW2DContextBW(IMG_UINT32 ui32BridgeID,
+							 PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT *psSGXRegHW2DContextIN,
+							 PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT *psSGXRegHW2DContextOUT,
+							 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hHW2DContextInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHW2DContextOUT->eError, psPerProc, 1);
+
+	psSGXRegHW2DContextOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSGXRegHW2DContextIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psSGXRegHW2DContextOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	hHW2DContextInt =
+		SGXRegisterHW2DContextKM(hDevCookieInt,
+								 &psSGXRegHW2DContextIN->sHW2DContextDevVAddr,
+								 psPerProc);
+
+	if (hHW2DContextInt == IMG_NULL)
+	{
+		psSGXRegHW2DContextOUT->eError = PVRSRV_ERROR_GENERIC;
+		return 0;
+	}
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psSGXRegHW2DContextOUT->hHW2DContext,
+					  hHW2DContextInt,
+					  PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHW2DContextOUT->eError, psPerProc);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHW2DContextBW(IMG_UINT32 ui32BridgeID,
+							   PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT *psSGXUnregHW2DContextIN,
+							   PVRSRV_BRIDGE_RETURN *psRetOUT,
+							   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hHW2DContextInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hHW2DContextInt,
+						   psSGXUnregHW2DContextIN->hHW2DContext,
+						   PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = SGXUnregisterHW2DContextKM(hHW2DContextInt);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psSGXUnregHW2DContextIN->hHW2DContext,
+							PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT);
+
+	return 0;
+}
+#endif
+
+static IMG_INT
+SGXFlushHWRenderTargetBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET *psSGXFlushHWRenderTargetIN,
+						  PVRSRV_BRIDGE_RETURN *psRetOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSGXFlushHWRenderTargetIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	SGXFlushHWRenderTargetKM(hDevCookieInt, psSGXFlushHWRenderTargetIN->sHWRTDataSetDevVAddr);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGX2DQueryBlitsCompleteBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE *ps2DQueryBltsCompleteIN,
+						  PVRSRV_BRIDGE_RETURN *psRetOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_VOID *pvSyncInfo;
+	PVRSRV_SGXDEV_INFO *psDevInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   ps2DQueryBltsCompleteIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+						   ps2DQueryBltsCompleteIN->hKernSyncInfo,
+						   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+	psRetOUT->eError =
+		SGX2DQueryBlitsCompleteKM(psDevInfo,
+								  (PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo,
+								  ps2DQueryBltsCompleteIN->bWaitForComplete);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXFindSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescIN,
+					  PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos = IMG_NULL;
+	IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount = 0;
+	IMG_UINT32 i;
+	IMG_HANDLE hSharedPBDesc = IMG_NULL;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psSGXFindSharedPBDescOUT->eError, psPerProc, PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS + 4);
+
+	psSGXFindSharedPBDescOUT->hSharedPBDesc = IMG_NULL;
+
+	psSGXFindSharedPBDescOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSGXFindSharedPBDescIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+		goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+
+	psSGXFindSharedPBDescOUT->eError =
+		SGXFindSharedPBDescKM(psPerProc, hDevCookieInt,
+							  psSGXFindSharedPBDescIN->bLockOnFailure,
+							  psSGXFindSharedPBDescIN->ui32TotalPBSize,
+							  &hSharedPBDesc,
+							  &psSharedPBDescKernelMemInfo,
+							  &psHWPBDescKernelMemInfo,
+							  &psBlockKernelMemInfo,
+							  &psHWBlockKernelMemInfo,
+							  &ppsSharedPBDescSubKernelMemInfos,
+							  &ui32SharedPBDescSubKernelMemInfosCount);
+	if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+		goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+
+	PVR_ASSERT(ui32SharedPBDescSubKernelMemInfosCount
+			   <= PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS);
+
+	psSGXFindSharedPBDescOUT->ui32SharedPBDescSubKernelMemInfoHandlesCount =
+		ui32SharedPBDescSubKernelMemInfosCount;
+
+	if(hSharedPBDesc == IMG_NULL)
+	{
+		psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle = 0;
+
+		goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+	}
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psSGXFindSharedPBDescOUT->hSharedPBDesc,
+					  hSharedPBDesc,
+					  PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+					  &psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle,
+					  psSharedPBDescKernelMemInfo,
+					  PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+					  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+					  psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+					  &psSGXFindSharedPBDescOUT->hHWPBDescKernelMemInfoHandle,
+					  psHWPBDescKernelMemInfo,
+					  PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+					  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+					  psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+				  &psSGXFindSharedPBDescOUT->hBlockKernelMemInfoHandle,
+				  psBlockKernelMemInfo,
+				  PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+				  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+				  psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+				  &psSGXFindSharedPBDescOUT->hHWBlockKernelMemInfoHandle,
+				  psHWBlockKernelMemInfo,
+				  PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+				  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+				  psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+
+	for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++)
+	{
+		PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOut =
+			psSGXFindSharedPBDescOUT;
+
+			PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+							  &psSGXFindSharedPBDescOut->ahSharedPBDescSubKernelMemInfoHandles[i],
+							  ppsSharedPBDescSubKernelMemInfos[i],
+							  PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+							  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+							  psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle);
+	}
+
+PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT:
+	if (ppsSharedPBDescSubKernelMemInfos != IMG_NULL)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount,
+				  ppsSharedPBDescSubKernelMemInfos,
+				  IMG_NULL);
+	}
+
+	if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+	{
+		if(hSharedPBDesc != IMG_NULL)
+		{
+			SGXUnrefSharedPBDescKM(hSharedPBDesc);
+		}
+	}
+	else
+	{
+		COMMIT_HANDLE_BATCH_OR_ERROR(psSGXFindSharedPBDescOUT->eError, psPerProc);
+	}
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXUnrefSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescIN,
+					   PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hSharedPBDesc;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC);
+
+	psSGXUnrefSharedPBDescOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hSharedPBDesc,
+						   psSGXUnrefSharedPBDescIN->hSharedPBDesc,
+						   PVRSRV_HANDLE_TYPE_SHARED_PB_DESC);
+	if(psSGXUnrefSharedPBDescOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psSGXUnrefSharedPBDescOUT->eError =
+		SGXUnrefSharedPBDescKM(hSharedPBDesc);
+
+	if(psSGXUnrefSharedPBDescOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psSGXUnrefSharedPBDescOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+						   psSGXUnrefSharedPBDescIN->hSharedPBDesc,
+						   PVRSRV_HANDLE_TYPE_SHARED_PB_DESC);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXAddSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+					 PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescIN,
+					 PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescOUT,
+					 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+	IMG_UINT32 ui32KernelMemInfoHandlesCount =
+		psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount;
+	IMG_INT ret = 0;
+	IMG_HANDLE *phKernelMemInfoHandles = IMG_NULL;
+	PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfos = IMG_NULL;
+	IMG_UINT32 i;
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hSharedPBDesc = IMG_NULL;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError, psPerProc, 1);
+
+	psSGXAddSharedPBDescOUT->hSharedPBDesc = IMG_NULL;
+
+	PVR_ASSERT(ui32KernelMemInfoHandlesCount
+			   <= PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS);
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+								&hDevCookieInt,
+								psSGXAddSharedPBDescIN->hDevCookie,
+								PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(eError != PVRSRV_OK)
+	{
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+								(IMG_VOID **)&psSharedPBDescKernelMemInfo,
+								psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo,
+								PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+	if(eError != PVRSRV_OK)
+	{
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+								(IMG_VOID **)&psHWPBDescKernelMemInfo,
+								psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo,
+								PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(eError != PVRSRV_OK)
+	{
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+								(IMG_VOID **)&psBlockKernelMemInfo,
+								psSGXAddSharedPBDescIN->hBlockKernelMemInfo,
+								PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+	if(eError != PVRSRV_OK)
+	{
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+								(IMG_VOID **)&psHWBlockKernelMemInfo,
+								psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo,
+								PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(eError != PVRSRV_OK)
+	{
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+
+	if(!OSAccessOK(PVR_VERIFY_READ,
+				   psSGXAddSharedPBDescIN->phKernelMemInfoHandles,
+				   ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE)))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC:"
+				 " Invalid phKernelMemInfos pointer", __FUNCTION__));
+		ret = -EFAULT;
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE),
+				  (IMG_VOID **)&phKernelMemInfoHandles,
+				  0,
+				  "Array of Handles");
+	if (eError != PVRSRV_OK)
+	{
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	if(CopyFromUserWrapper(psPerProc,
+			               ui32BridgeID,
+			               phKernelMemInfoHandles,
+						   psSGXAddSharedPBDescIN->phKernelMemInfoHandles,
+						   ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE))
+	   != PVRSRV_OK)
+	{
+		ret = -EFAULT;
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  ui32KernelMemInfoHandlesCount * sizeof(PVRSRV_KERNEL_MEM_INFO *),
+				  (IMG_VOID **)&ppsKernelMemInfos,
+				  0,
+				  "Array of pointers to Kernel Memory Info");
+	if (eError != PVRSRV_OK)
+	{
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	for(i=0; i<ui32KernelMemInfoHandlesCount; i++)
+	{
+		eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+									(IMG_VOID **)&ppsKernelMemInfos[i],
+									phKernelMemInfoHandles[i],
+									PVRSRV_HANDLE_TYPE_MEM_INFO);
+		if(eError != PVRSRV_OK)
+		{
+			goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+		}
+	}
+
+
+
+	eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+								psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo,
+								PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+
+	eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+								psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo,
+								PVRSRV_HANDLE_TYPE_MEM_INFO);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+
+	eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+								psSGXAddSharedPBDescIN->hBlockKernelMemInfo,
+								PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+
+	eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+								psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo,
+								PVRSRV_HANDLE_TYPE_MEM_INFO);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+	for(i=0; i<ui32KernelMemInfoHandlesCount; i++)
+	{
+
+		eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+									phKernelMemInfoHandles[i],
+									PVRSRV_HANDLE_TYPE_MEM_INFO);
+		PVR_ASSERT(eError == PVRSRV_OK);
+	}
+
+	eError = SGXAddSharedPBDescKM(psPerProc, hDevCookieInt,
+								  psSharedPBDescKernelMemInfo,
+								  psHWPBDescKernelMemInfo,
+								  psBlockKernelMemInfo,
+								  psHWBlockKernelMemInfo,
+								  psSGXAddSharedPBDescIN->ui32TotalPBSize,
+								  &hSharedPBDesc,
+								  ppsKernelMemInfos,
+								  ui32KernelMemInfoHandlesCount);
+
+
+	if (eError != PVRSRV_OK)
+	{
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+				  &psSGXAddSharedPBDescOUT->hSharedPBDesc,
+				  hSharedPBDesc,
+				  PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+				  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT:
+
+	if(phKernelMemInfoHandles)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE),
+				  (IMG_VOID *)phKernelMemInfoHandles,
+				  0);
+	}
+	if(ppsKernelMemInfos)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount * sizeof(PVRSRV_KERNEL_MEM_INFO *),
+				  (IMG_VOID *)ppsKernelMemInfos,
+				  0);
+	}
+
+	if(ret == 0 && eError == PVRSRV_OK)
+	{
+		COMMIT_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError, psPerProc);
+	}
+
+	psSGXAddSharedPBDescOUT->eError = eError;
+
+	return ret;
+}
+
+static IMG_INT
+SGXGetInfoForSrvinitBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitIN,
+					   PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_UINT32 i;
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psSGXInfoForSrvinitOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS);
+
+	if(!psPerProc->bInitProcess)
+	{
+		psSGXInfoForSrvinitOUT->eError = PVRSRV_ERROR_GENERIC;
+		return 0;
+	}
+
+	psSGXInfoForSrvinitOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psSGXInfoForSrvinitIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psSGXInfoForSrvinitOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psSGXInfoForSrvinitOUT->eError =
+		SGXGetInfoForSrvinitKM(hDevCookieInt,
+							   &psSGXInfoForSrvinitOUT->sInitInfo);
+
+	if(psSGXInfoForSrvinitOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	for(i = 0; i < PVRSRV_MAX_CLIENT_HEAPS; i++)
+	{
+		PVRSRV_HEAP_INFO *psHeapInfo;
+
+		psHeapInfo = &psSGXInfoForSrvinitOUT->sInitInfo.asHeapInfo[i];
+
+		if (psHeapInfo->ui32HeapID != (IMG_UINT32)SGX_UNDEFINED_HEAP_ID)
+		{
+			IMG_HANDLE hDevMemHeapExt;
+
+			if (psHeapInfo->hDevMemHeap != IMG_NULL)
+			{
+
+				PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+								  &hDevMemHeapExt,
+								  psHeapInfo->hDevMemHeap,
+								  PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+								  PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+				psHeapInfo->hDevMemHeap = hDevMemHeapExt;
+			}
+		}
+	}
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psSGXInfoForSrvinitOUT->eError, psPerProc);
+
+	return 0;
+}
+
+#if defined(PDUMP)
+static IMG_VOID
+DumpBufferArray(PVRSRV_PER_PROCESS_DATA *psPerProc,
+				PSGX_KICKTA_DUMP_BUFFER	psBufferArray,
+				IMG_UINT32						ui32BufferArrayLength,
+				IMG_BOOL						bDumpPolls)
+{
+	IMG_UINT32	i;
+
+	for (i=0; i<ui32BufferArrayLength; i++)
+	{
+		PSGX_KICKTA_DUMP_BUFFER	psBuffer;
+		PVRSRV_KERNEL_MEM_INFO 	*psCtrlMemInfoKM;
+		IMG_CHAR * pszName;
+		IMG_HANDLE hUniqueTag;
+		IMG_UINT32	ui32Offset;
+
+		psBuffer = &psBufferArray[i];
+		pszName = psBuffer->pszName;
+		if (!pszName)
+		{
+			pszName = "Nameless buffer";
+		}
+
+		hUniqueTag = MAKEUNIQUETAG((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hKernelMemInfo);
+
+	#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+		psCtrlMemInfoKM	= ((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hCtrlKernelMemInfo);
+		ui32Offset =  psBuffer->sCtrlDevVAddr.uiAddr - psCtrlMemInfoKM->sDevVAddr.uiAddr;
+	#else
+		psCtrlMemInfoKM = ((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hKernelMemInfo)->psKernelSyncInfo->psSyncDataMemInfoKM;
+		ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+	#endif
+
+		if (psBuffer->ui32Start <= psBuffer->ui32End)
+		{
+			if (bDumpPolls)
+			{
+				PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+				PDUMPCBP(psCtrlMemInfoKM,
+						 ui32Offset,
+						 psBuffer->ui32Start,
+						 psBuffer->ui32SpaceUsed,
+						 psBuffer->ui32BufferSize,
+						 0,
+						 MAKEUNIQUETAG(psCtrlMemInfoKM));
+			}
+
+			PDUMPCOMMENTWITHFLAGS(0, "%s\r\n", pszName);
+			PDUMPMEMUM(psPerProc,
+					 IMG_NULL,
+					 psBuffer->pvLinAddr,
+					 (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+					 psBuffer->ui32Start,
+					 psBuffer->ui32End - psBuffer->ui32Start,
+					 0,
+					 hUniqueTag);
+		}
+		else
+		{
+
+
+			if (bDumpPolls)
+			{
+				PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+				PDUMPCBP(psCtrlMemInfoKM,
+						 ui32Offset,
+						 psBuffer->ui32Start,
+						 psBuffer->ui32BackEndLength,
+						 psBuffer->ui32BufferSize,
+						 0,
+						 MAKEUNIQUETAG(psCtrlMemInfoKM));
+			}
+			PDUMPCOMMENTWITHFLAGS(0, "%s (part 1)\r\n", pszName);
+			PDUMPMEMUM(psPerProc,
+					 IMG_NULL,
+					 psBuffer->pvLinAddr,
+					 (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+					 psBuffer->ui32Start,
+					 psBuffer->ui32BackEndLength,
+					 0,
+					 hUniqueTag);
+
+			if (bDumpPolls)
+			{
+				PDUMPMEMPOL(psCtrlMemInfoKM,
+							ui32Offset,
+							0,
+							0xFFFFFFFF,
+							PDUMP_POLL_OPERATOR_NOTEQUAL,
+							0,
+							MAKEUNIQUETAG(psCtrlMemInfoKM));
+
+				PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+				PDUMPCBP(psCtrlMemInfoKM,
+						 ui32Offset,
+						 0,
+						 psBuffer->ui32End,
+						 psBuffer->ui32BufferSize,
+						 0,
+						 MAKEUNIQUETAG(psCtrlMemInfoKM));
+			}
+			PDUMPCOMMENTWITHFLAGS(0, "%s (part 2)\r\n", pszName);
+			PDUMPMEMUM(psPerProc,
+					 IMG_NULL,
+					 psBuffer->pvLinAddr,
+					 (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+					 0,
+					 psBuffer->ui32End,
+					 0,
+					 hUniqueTag);
+		}
+	}
+}
+static IMG_INT
+SGXPDumpBufferArrayBW(IMG_UINT32 ui32BridgeID,
+				   PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY *psPDumpBufferArrayIN,
+				   IMG_VOID *psBridgeOut,
+				   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_UINT32 i;
+	SGX_KICKTA_DUMP_BUFFER *psKickTADumpBuffer;
+	IMG_UINT32 ui32BufferArrayLength =
+		psPDumpBufferArrayIN->ui32BufferArrayLength;
+	IMG_UINT32 ui32BufferArraySize =
+		ui32BufferArrayLength * sizeof(SGX_KICKTA_DUMP_BUFFER);
+	PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
+
+	PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY);
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  ui32BufferArraySize,
+				  (IMG_PVOID *)&psKickTADumpBuffer, 0,
+				  "Array of Kick Tile Accelerator Dump Buffer") != PVRSRV_OK)
+	{
+		return -ENOMEM;
+	}
+
+	if(CopyFromUserWrapper(psPerProc,
+			               ui32BridgeID,
+						   psKickTADumpBuffer,
+						   psPDumpBufferArrayIN->psBufferArray,
+						   ui32BufferArraySize) != PVRSRV_OK)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
+
+		return -EFAULT;
+	}
+
+	for(i = 0; i < ui32BufferArrayLength; i++)
+	{
+		IMG_VOID *pvMemInfo;
+
+		eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+									&pvMemInfo,
+									psKickTADumpBuffer[i].hKernelMemInfo,
+									PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY: "
+					 "PVRSRVLookupHandle failed (%d)", eError));
+			break;
+		}
+		psKickTADumpBuffer[i].hKernelMemInfo = pvMemInfo;
+
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+		eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+									&pvMemInfo,
+									psKickTADumpBuffer[i].hCtrlKernelMemInfo,
+									PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY: "
+					 "PVRSRVLookupHandle failed (%d)", eError));
+			break;
+		}
+		psKickTADumpBuffer[i].hCtrlKernelMemInfo = pvMemInfo;
+#endif
+	}
+
+	if(eError == PVRSRV_OK)
+	{
+		DumpBufferArray(psPerProc,
+						psKickTADumpBuffer,
+						ui32BufferArrayLength,
+						psPDumpBufferArrayIN->bDumpPolls);
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
+
+
+	return 0;
+}
+
+static IMG_INT
+SGXPDump3DSignatureRegistersBW(IMG_UINT32 ui32BridgeID,
+				   PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS *psPDump3DSignatureRegistersIN,
+				   PVRSRV_BRIDGE_RETURN *psRetOUT,
+				   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_UINT32 ui32RegisterArraySize =  psPDump3DSignatureRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+	IMG_UINT32 *pui32Registers = IMG_NULL;
+#if defined(SGX_FEATURE_MP)	&& defined(FIX_HW_BRN_27270)
+	PVRSRV_SGXDEV_INFO	*psDevInfo = IMG_NULL;
+	IMG_HANDLE 	hDevCookieInt;
+	IMG_UINT32	ui32RegVal = 0;
+#endif
+	IMG_INT ret = -EFAULT;
+
+	PVR_UNREFERENCED_PARAMETER(psRetOUT);
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS);
+
+	if (ui32RegisterArraySize == 0)
+	{
+		goto ExitNoError;
+	}
+
+#if defined(SGX_FEATURE_MP)	&& defined(FIX_HW_BRN_27270)
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psPDump3DSignatureRegistersIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: hDevCookie lookup failed"));
+		goto Exit;
+	}
+
+	psDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+
+	ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
+#if defined(PDUMP)
+	PDUMPREGWITHFLAGS(EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT,
+						psPDump3DSignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+#endif
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  ui32RegisterArraySize,
+				  (IMG_PVOID *)&pui32Registers, 0,
+				  "Array of Registers") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDump3DSignatureRegistersBW: OSAllocMem failed"));
+		goto Exit;
+	}
+
+	if(CopyFromUserWrapper(psPerProc,
+			        	ui32BridgeID,
+					pui32Registers,
+					psPDump3DSignatureRegistersIN->pui32Registers,
+					ui32RegisterArraySize) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDump3DSignatureRegistersBW: CopyFromUserWrapper failed"));
+		goto Exit;
+	}
+
+	PDump3DSignatureRegisters(psPDump3DSignatureRegistersIN->ui32DumpFrameNum,
+					psPDump3DSignatureRegistersIN->bLastFrame,
+					pui32Registers,
+					psPDump3DSignatureRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+	psRetOUT->eError = PVRSRV_OK;
+	ret = 0;
+Exit:
+	if (pui32Registers != IMG_NULL)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+	}
+
+#if defined(SGX_FEATURE_MP)	&& defined(FIX_HW_BRN_27270)
+	if (psDevInfo != IMG_NULL)
+	{
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, ui32RegVal);
+#if defined(PDUMP)
+		PDUMPREGWITHFLAGS(EUR_CR_MASTER_CORE, ui32RegVal,
+							psPDump3DSignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+	}
+#endif
+
+	return ret;
+}
+
+static IMG_INT
+SGXPDumpCounterRegistersBW(IMG_UINT32 ui32BridgeID,
+				   PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS *psPDumpCounterRegistersIN,
+				   IMG_VOID *psBridgeOut,
+				   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_UINT32 ui32RegisterArraySize =  psPDumpCounterRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+	IMG_UINT32 *pui32Registers = IMG_NULL;
+	IMG_INT ret = -EFAULT;
+
+	PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS);
+
+	if (ui32RegisterArraySize == 0)
+	{
+		goto ExitNoError;
+	}
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  ui32RegisterArraySize,
+				  (IMG_PVOID *)&pui32Registers, 0,
+				  "Array of Registers") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpCounterRegistersBW: OSAllocMem failed"));
+		ret = -ENOMEM;
+		goto Exit;
+	}
+
+	if(CopyFromUserWrapper(psPerProc,
+			        	ui32BridgeID,
+					pui32Registers,
+					psPDumpCounterRegistersIN->pui32Registers,
+					ui32RegisterArraySize) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpCounterRegistersBW: CopyFromUserWrapper failed"));
+		goto Exit;
+	}
+
+	PDumpCounterRegisters(psPDumpCounterRegistersIN->ui32DumpFrameNum,
+					psPDumpCounterRegistersIN->bLastFrame,
+					pui32Registers,
+					psPDumpCounterRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+	ret = 0;
+Exit:
+	if (pui32Registers != IMG_NULL)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+	}
+
+	return ret;
+}
+
+static IMG_INT
+SGXPDumpTASignatureRegistersBW(IMG_UINT32 ui32BridgeID,
+				   PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS *psPDumpTASignatureRegistersIN,
+				   PVRSRV_BRIDGE_RETURN *psRetOUT,
+				   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_UINT32 ui32RegisterArraySize =  psPDumpTASignatureRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+	IMG_UINT32 *pui32Registers = IMG_NULL;
+#if defined(SGX_FEATURE_MP)	&& defined(FIX_HW_BRN_27270)
+	PVRSRV_SGXDEV_INFO	*psDevInfo = IMG_NULL;
+	IMG_HANDLE hDevCookieInt;
+	IMG_UINT32	ui32RegVal = 0;
+#endif
+	IMG_INT ret = -EFAULT;
+
+	PVR_UNREFERENCED_PARAMETER(psRetOUT);
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS);
+
+	if (ui32RegisterArraySize == 0)
+	{
+		goto ExitNoError;
+	}
+
+#if defined(SGX_FEATURE_MP)	&& defined(FIX_HW_BRN_27270)
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psPDumpTASignatureRegistersIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: hDevCookie lookup failed"));
+		goto Exit;
+	}
+
+	psDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+
+	ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
+#if defined(PDUMP)
+	PDUMPREGWITHFLAGS(EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT,
+						psPDumpTASignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+#endif
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  ui32RegisterArraySize,
+				  (IMG_PVOID *)&pui32Registers, 0,
+				  "Array of Registers") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: OSAllocMem failed"));
+		ret = -ENOMEM;
+		goto Exit;
+	}
+
+	if(CopyFromUserWrapper(psPerProc,
+			        	ui32BridgeID,
+					pui32Registers,
+					psPDumpTASignatureRegistersIN->pui32Registers,
+					ui32RegisterArraySize) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: CopyFromUserWrapper failed"));
+		goto Exit;
+	}
+
+	PDumpTASignatureRegisters(psPDumpTASignatureRegistersIN->ui32DumpFrameNum,
+					psPDumpTASignatureRegistersIN->ui32TAKickCount,
+					psPDumpTASignatureRegistersIN->bLastFrame,
+					pui32Registers,
+					psPDumpTASignatureRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+	psRetOUT->eError = PVRSRV_OK;
+	ret = 0;
+Exit:
+	if (pui32Registers != IMG_NULL)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+	}
+
+#if defined(SGX_FEATURE_MP)	&& defined(FIX_HW_BRN_27270)
+	if (psDevInfo != IMG_NULL)
+	{
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, ui32RegVal);
+#if defined(PDUMP)
+		PDUMPREGWITHFLAGS(EUR_CR_MASTER_CORE, ui32RegVal,
+							psPDumpTASignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+	}
+#endif
+
+	return ret;
+}
+static IMG_INT
+SGXPDumpHWPerfCBBW(IMG_UINT32						ui32BridgeID,
+				   PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB	*psPDumpHWPerfCBIN,
+				   PVRSRV_BRIDGE_RETURN 			*psRetOUT,
+				   PVRSRV_PER_PROCESS_DATA 			*psPerProc)
+{
+#if defined(SUPPORT_SGX_HWPERF)
+#if defined(__linux__)
+	PVRSRV_SGXDEV_INFO	*psDevInfo;
+	IMG_HANDLE			hDevCookieInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psPDumpHWPerfCBIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+	PDumpHWPerfCBKM(&psPDumpHWPerfCBIN->szFileName[0],
+					psPDumpHWPerfCBIN->ui32FileOffset,
+					psDevInfo->psKernelHWPerfCBMemInfo->sDevVAddr,
+					psDevInfo->psKernelHWPerfCBMemInfo->ui32AllocSize,
+					psPDumpHWPerfCBIN->ui32PDumpFlags);
+
+	return 0;
+#else
+	PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+	PVR_UNREFERENCED_PARAMETER(psPDumpHWPerfCBIN);
+	PVR_UNREFERENCED_PARAMETER(psRetOUT);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+	return 0;
+#endif
+#else
+	PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+	PVR_UNREFERENCED_PARAMETER(psPDumpHWPerfCBIN);
+	PVR_UNREFERENCED_PARAMETER(psRetOUT);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+	return -EFAULT;
+#endif
+}
+
+#endif
+
+
+IMG_VOID SetSGXDispatchTableEntry(IMG_VOID)
+{
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETCLIENTINFO, SGXGetClientInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO, SGXReleaseClientInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO, SGXGetInternalDevInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_DOKICK, SGXDoKickBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETPHYSPAGEADDR, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READREGISTRYDWORD, DummyBW);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE, SGX2DQueryBlitsCompleteBW);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETMMUPDADDR, DummyBW);
+
+#if defined(TRANSFER_QUEUE)
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SUBMITTRANSFER, SGXSubmitTransferBW);
+#endif
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETMISCINFO, SGXGetMiscInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT	, SGXGetInfoForSrvinitBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_DEVINITPART2, SGXDevInitPart2BW);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC, SGXFindSharedPBDescBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC, SGXUnrefSharedPBDescBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC, SGXAddSharedPBDescBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT, SGXRegisterHWRenderContextBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET, SGXFlushHWRenderTargetBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT, SGXUnregisterHWRenderContextBW);
+#if defined(SGX_FEATURE_2D_HARDWARE)
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SUBMIT2D, SGXSubmit2DBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT, SGXRegisterHW2DContextBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT, SGXUnregisterHW2DContextBW);
+#endif
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT, SGXRegisterHWTransferContextBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT, SGXUnregisterHWTransferContextBW);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES, SGXScheduleProcessQueuesBW);
+
+#if defined(SUPPORT_SGX_HWPERF)
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READ_DIFF_COUNTERS, SGXReadDiffCountersBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READ_HWPERF_CB, SGXReadHWPerfCBBW);
+#endif
+
+#if defined(PDUMP)
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY, SGXPDumpBufferArrayBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS, SGXPDump3DSignatureRegistersBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS, SGXPDumpCounterRegistersBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS, SGXPDumpTASignatureRegistersBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB, SGXPDumpHWPerfCBBW);
+#endif
+}
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h
new file mode 100644
index 0000000..ba2a3c8
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h
@@ -0,0 +1,38 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __BRIDGED_SGX_BRIDGE_H__
+#define __BRIDGED_SGX_BRIDGE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+IMG_VOID SetSGXDispatchTableEntry(IMG_VOID);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/buffer_manager.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/buffer_manager.c
new file mode 100644
index 0000000..ecb5d03
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/buffer_manager.c
@@ -0,0 +1,2069 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+
+#include "sysconfig.h"
+#include "hash.h"
+#include "ra.h"
+#include "pdump_km.h"
+
+#define MIN(a,b)       (a > b ? b : a)
+
+
+#include "lists.h"
+
+DECLARE_LIST_ANY_VA(BM_HEAP);
+DECLARE_LIST_ANY_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_ANY_VA_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH_VA(BM_HEAP);
+DECLARE_LIST_INSERT(BM_HEAP);
+DECLARE_LIST_REMOVE(BM_HEAP);
+
+DECLARE_LIST_FOR_EACH(BM_CONTEXT);
+DECLARE_LIST_ANY_VA(BM_CONTEXT);
+DECLARE_LIST_ANY_VA_2(BM_CONTEXT, IMG_HANDLE, IMG_NULL);
+DECLARE_LIST_INSERT(BM_CONTEXT);
+DECLARE_LIST_REMOVE(BM_CONTEXT);
+
+
+static IMG_BOOL
+ZeroBuf(BM_BUF *pBuf, BM_MAPPING *pMapping, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags);
+static IMG_VOID
+BM_FreeMemory (IMG_VOID *pH, IMG_UINTPTR_T base, BM_MAPPING *psMapping);
+static IMG_BOOL
+BM_ImportMemory(IMG_VOID *pH, IMG_SIZE_T uSize,
+					IMG_SIZE_T *pActualSize, BM_MAPPING **ppsMapping,
+					IMG_UINT32 uFlags, IMG_UINTPTR_T *pBase);
+
+static IMG_BOOL
+DevMemoryAlloc (BM_CONTEXT *pBMContext,
+				BM_MAPPING *pMapping,
+				IMG_SIZE_T *pActualSize,
+				IMG_UINT32 uFlags,
+				IMG_UINT32 dev_vaddr_alignment,
+				IMG_DEV_VIRTADDR *pDevVAddr);
+static IMG_VOID
+DevMemoryFree (BM_MAPPING *pMapping);
+
+static IMG_BOOL
+AllocMemory (BM_CONTEXT				*pBMContext,
+				BM_HEAP				*psBMHeap,
+				IMG_DEV_VIRTADDR	*psDevVAddr,
+				IMG_SIZE_T			uSize,
+				IMG_UINT32			uFlags,
+				IMG_UINT32			uDevVAddrAlignment,
+				BM_BUF				*pBuf)
+{
+	BM_MAPPING			*pMapping;
+	IMG_UINTPTR_T		uOffset;
+	RA_ARENA			*pArena = IMG_NULL;
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "AllocMemory (pBMContext=%08X, uSize=0x%x, uFlags=0x%x, align=0x%x, pBuf=%08X)",
+			  pBMContext, uSize, uFlags, uDevVAddrAlignment, pBuf));
+
+
+
+
+	if(uFlags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+	{
+		if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+		{
+
+			PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: combination of DevVAddr management and RAM backing mode unsupported"));
+			return IMG_FALSE;
+		}
+
+
+
+
+		if(psBMHeap->ui32Attribs
+		   &	(PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+		   |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+		{
+
+			pArena = psBMHeap->pImportArena;
+		}
+		else
+		{
+			PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: backing store type doesn't match heap"));
+			return IMG_FALSE;
+		}
+
+
+		if (!RA_Alloc(pArena,
+					  uSize,
+					  IMG_NULL,
+					  (IMG_VOID*) &pMapping,
+					  uFlags,
+					  uDevVAddrAlignment,
+					  0,
+					  (IMG_UINTPTR_T *)&(pBuf->DevVAddr.uiAddr)))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "AllocMemory: RA_Alloc(0x%x) FAILED", uSize));
+			return IMG_FALSE;
+		}
+
+		uOffset = pBuf->DevVAddr.uiAddr - pMapping->DevVAddr.uiAddr;
+		if(pMapping->CpuVAddr)
+		{
+			pBuf->CpuVAddr = (IMG_VOID*) ((IMG_UINTPTR_T)pMapping->CpuVAddr + uOffset);
+		}
+		else
+		{
+			pBuf->CpuVAddr = IMG_NULL;
+		}
+
+		if(uSize == pMapping->uSize)
+		{
+			pBuf->hOSMemHandle = pMapping->hOSMemHandle;
+		}
+		else
+		{
+			if(OSGetSubMemHandle(pMapping->hOSMemHandle,
+								 uOffset,
+								 uSize,
+								 psBMHeap->ui32Attribs,
+								 &pBuf->hOSMemHandle)!=PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "AllocMemory: OSGetSubMemHandle FAILED"));
+				return IMG_FALSE;
+			}
+		}
+
+
+		pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + uOffset;
+
+		if(uFlags & PVRSRV_MEM_ZERO)
+		{
+			if(!ZeroBuf(pBuf, pMapping, uSize, psBMHeap->ui32Attribs | uFlags))
+			{
+				return IMG_FALSE;
+			}
+		}
+	}
+	else
+	{
+		if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+		{
+
+			PVR_ASSERT(psDevVAddr != IMG_NULL);
+
+			if (psDevVAddr == IMG_NULL)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "AllocMemory: invalid parameter - psDevVAddr"));
+				return IMG_FALSE;
+			}
+
+
+			pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
+													uSize,
+													IMG_NULL,
+													PVRSRV_MEM_USER_SUPPLIED_DEVVADDR,
+													uDevVAddrAlignment,
+													psDevVAddr);
+
+
+			pBuf->DevVAddr = *psDevVAddr;
+		}
+		else
+		{
+
+
+
+			pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
+													uSize,
+													IMG_NULL,
+													0,
+													uDevVAddrAlignment,
+													&pBuf->DevVAddr);
+		}
+
+
+		if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+							sizeof (struct _BM_MAPPING_),
+							(IMG_PVOID *)&pMapping, IMG_NULL,
+							"Buffer Manager Mapping") != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "AllocMemory: OSAllocMem(0x%x) FAILED"));
+			return IMG_FALSE;
+		}
+
+
+		pBuf->CpuVAddr = IMG_NULL;
+		pBuf->hOSMemHandle = 0;
+		pBuf->CpuPAddr.uiAddr = 0;
+
+
+		pMapping->CpuVAddr = IMG_NULL;
+		pMapping->CpuPAddr.uiAddr = 0;
+		pMapping->DevVAddr = pBuf->DevVAddr;
+		pMapping->psSysAddr = IMG_NULL;
+		pMapping->uSize = uSize;
+		pMapping->hOSMemHandle = 0;
+	}
+
+
+	pMapping->pArena = pArena;
+
+
+	pMapping->pBMHeap = psBMHeap;
+	pBuf->pMapping = pMapping;
+
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+				"AllocMemory: pMapping=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
+				pMapping,
+				pMapping->DevVAddr.uiAddr,
+				pMapping->CpuVAddr,
+				pMapping->CpuPAddr.uiAddr,
+				pMapping->uSize));
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+				"AllocMemory: pBuf=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
+				pBuf,
+				pBuf->DevVAddr.uiAddr,
+				pBuf->CpuVAddr,
+				pBuf->CpuPAddr.uiAddr,
+				uSize));
+
+
+	PVR_ASSERT(((pBuf->DevVAddr.uiAddr) & (uDevVAddrAlignment - 1)) == 0);
+
+	return IMG_TRUE;
+}
+
+
+static IMG_BOOL
+WrapMemory (BM_HEAP *psBMHeap,
+			IMG_SIZE_T uSize,
+			IMG_SIZE_T ui32BaseOffset,
+			IMG_BOOL bPhysContig,
+			IMG_SYS_PHYADDR *psAddr,
+			IMG_VOID *pvCPUVAddr,
+			IMG_UINT32 uFlags,
+			BM_BUF *pBuf)
+{
+	IMG_DEV_VIRTADDR DevVAddr = {0};
+	BM_MAPPING *pMapping;
+	IMG_BOOL bResult;
+	IMG_SIZE_T const ui32PageSize = HOST_PAGESIZE();
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "WrapMemory(psBMHeap=%08X, size=0x%x, offset=0x%x, bPhysContig=0x%x, pvCPUVAddr = 0x%x, flags=0x%x, pBuf=%08X)",
+			  psBMHeap, uSize, ui32BaseOffset, bPhysContig, pvCPUVAddr, uFlags, pBuf));
+
+	PVR_ASSERT((psAddr->uiAddr & (ui32PageSize - 1)) == 0);
+
+	PVR_ASSERT(((IMG_UINTPTR_T)pvCPUVAddr & (ui32PageSize - 1)) == 0);
+
+	uSize += ui32BaseOffset;
+	uSize = HOST_PAGEALIGN (uSize);
+
+
+	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof(*pMapping),
+						(IMG_PVOID *)&pMapping, IMG_NULL,
+						"Mocked-up mapping") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSAllocMem(0x%x) FAILED",sizeof(*pMapping)));
+		return IMG_FALSE;
+	}
+
+	OSMemSet(pMapping, 0, sizeof (*pMapping));
+
+	pMapping->uSize = uSize;
+	pMapping->pBMHeap = psBMHeap;
+
+	if(pvCPUVAddr)
+	{
+		pMapping->CpuVAddr = pvCPUVAddr;
+
+		if (bPhysContig)
+		{
+			pMapping->eCpuMemoryOrigin = hm_wrapped_virtaddr;
+			pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);
+
+			if(OSRegisterMem(pMapping->CpuPAddr,
+							pMapping->CpuVAddr,
+							pMapping->uSize,
+							uFlags,
+							&pMapping->hOSMemHandle) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,	"WrapMemory: OSRegisterMem Phys=0x%08X, CpuVAddr = 0x%08X, Size=%d) failed",
+					pMapping->CpuPAddr, pMapping->CpuVAddr, pMapping->uSize));
+				goto fail_cleanup;
+			}
+		}
+		else
+		{
+			pMapping->eCpuMemoryOrigin = hm_wrapped_scatter_virtaddr;
+			pMapping->psSysAddr = psAddr;
+
+			if(OSRegisterDiscontigMem(pMapping->psSysAddr,
+							pMapping->CpuVAddr,
+							pMapping->uSize,
+							uFlags,
+							&pMapping->hOSMemHandle) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,	"WrapMemory: OSRegisterDiscontigMem CpuVAddr = 0x%08X, Size=%d) failed",
+					pMapping->CpuVAddr, pMapping->uSize));
+				goto fail_cleanup;
+			}
+		}
+	}
+	else
+	{
+		if (bPhysContig)
+		{
+			pMapping->eCpuMemoryOrigin = hm_wrapped;
+			pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);
+
+			if(OSReservePhys(pMapping->CpuPAddr,
+							 pMapping->uSize,
+							 uFlags,
+							 &pMapping->CpuVAddr,
+							 &pMapping->hOSMemHandle) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,	"WrapMemory: OSReservePhys Phys=0x%08X, Size=%d) failed",
+					pMapping->CpuPAddr, pMapping->uSize));
+				goto fail_cleanup;
+			}
+		}
+		else
+		{
+			pMapping->eCpuMemoryOrigin = hm_wrapped_scatter;
+			pMapping->psSysAddr = psAddr;
+
+			if(OSReserveDiscontigPhys(pMapping->psSysAddr,
+							 pMapping->uSize,
+							 uFlags,
+							 &pMapping->CpuVAddr,
+							 &pMapping->hOSMemHandle) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,	"WrapMemory: OSReserveDiscontigPhys Size=%d) failed",
+					pMapping->uSize));
+				goto fail_cleanup;
+			}
+		}
+	}
+
+
+	bResult = DevMemoryAlloc(psBMHeap->pBMContext,
+							 pMapping,
+							 IMG_NULL,
+							 uFlags | PVRSRV_MEM_READ | PVRSRV_MEM_WRITE,
+							 IMG_CAST_TO_DEVVADDR_UINT(ui32PageSize),
+							 &DevVAddr);
+	if (!bResult)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"WrapMemory: DevMemoryAlloc(0x%x) failed",
+				pMapping->uSize));
+		goto fail_cleanup;
+	}
+
+
+	pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + ui32BaseOffset;
+	if(!ui32BaseOffset)
+	{
+		pBuf->hOSMemHandle = pMapping->hOSMemHandle;
+	}
+	else
+	{
+		if(OSGetSubMemHandle(pMapping->hOSMemHandle,
+							 ui32BaseOffset,
+							 (pMapping->uSize-ui32BaseOffset),
+							 uFlags,
+							 &pBuf->hOSMemHandle)!=PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSGetSubMemHandle failed"));
+			goto fail_cleanup;
+		}
+	}
+	if(pMapping->CpuVAddr)
+	{
+		pBuf->CpuVAddr = (IMG_VOID*) ((IMG_UINTPTR_T)pMapping->CpuVAddr + ui32BaseOffset);
+	}
+	pBuf->DevVAddr.uiAddr = pMapping->DevVAddr.uiAddr + IMG_CAST_TO_DEVVADDR_UINT(ui32BaseOffset);
+
+	if(uFlags & PVRSRV_MEM_ZERO)
+	{
+		if(!ZeroBuf(pBuf, pMapping, uSize, uFlags))
+		{
+			return IMG_FALSE;
+		}
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "DevVaddr.uiAddr=%08X", DevVAddr.uiAddr));
+	PVR_DPF ((PVR_DBG_MESSAGE,
+				"WrapMemory: pMapping=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
+				pMapping, pMapping->DevVAddr.uiAddr,
+				pMapping->CpuVAddr, pMapping->CpuPAddr.uiAddr, pMapping->uSize));
+	PVR_DPF ((PVR_DBG_MESSAGE,
+				"WrapMemory: pBuf=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
+				pBuf, pBuf->DevVAddr.uiAddr,
+				pBuf->CpuVAddr, pBuf->CpuPAddr.uiAddr, uSize));
+
+	pBuf->pMapping = pMapping;
+	return IMG_TRUE;
+
+fail_cleanup:
+	if(ui32BaseOffset && pBuf->hOSMemHandle)
+	{
+		OSReleaseSubMemHandle(pBuf->hOSMemHandle, uFlags);
+	}
+
+	if(pMapping && (pMapping->CpuVAddr || pMapping->hOSMemHandle))
+	{
+		switch(pMapping->eCpuMemoryOrigin)
+		{
+			case hm_wrapped:
+				OSUnReservePhys(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+				break;
+			case hm_wrapped_virtaddr:
+				OSUnRegisterMem(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+				break;
+			case hm_wrapped_scatter:
+				OSUnReserveDiscontigPhys(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+				break;
+			case hm_wrapped_scatter_virtaddr:
+				OSUnRegisterDiscontigMem(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+				break;
+			default:
+				break;
+		}
+
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+
+
+	return IMG_FALSE;
+}
+
+
+static IMG_BOOL
+ZeroBuf(BM_BUF *pBuf, BM_MAPPING *pMapping, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags)
+{
+	IMG_VOID *pvCpuVAddr;
+
+	if(pBuf->CpuVAddr)
+	{
+		OSMemSet(pBuf->CpuVAddr, 0, ui32Bytes);
+	}
+	else if(pMapping->eCpuMemoryOrigin == hm_contiguous
+			|| pMapping->eCpuMemoryOrigin == hm_wrapped)
+	{
+		pvCpuVAddr = OSMapPhysToLin(pBuf->CpuPAddr,
+									ui32Bytes,
+									PVRSRV_HAP_KERNEL_ONLY
+									| (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+									IMG_NULL);
+		if(!pvCpuVAddr)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "ZeroBuf: OSMapPhysToLin for contiguous buffer failed"));
+			return IMG_FALSE;
+		}
+		OSMemSet(pvCpuVAddr, 0, ui32Bytes);
+		OSUnMapPhysToLin(pvCpuVAddr,
+						 ui32Bytes,
+						 PVRSRV_HAP_KERNEL_ONLY
+						 | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+						 IMG_NULL);
+	}
+	else
+	{
+		IMG_SIZE_T ui32BytesRemaining = ui32Bytes;
+		IMG_SIZE_T ui32CurrentOffset = 0;
+		IMG_CPU_PHYADDR CpuPAddr;
+
+
+		PVR_ASSERT(pBuf->hOSMemHandle);
+
+		while(ui32BytesRemaining > 0)
+		{
+			IMG_SIZE_T ui32BlockBytes = MIN(ui32BytesRemaining, HOST_PAGESIZE());
+			CpuPAddr = OSMemHandleToCpuPAddr(pBuf->hOSMemHandle, ui32CurrentOffset);
+
+			if(CpuPAddr.uiAddr & (HOST_PAGESIZE() -1))
+			{
+				ui32BlockBytes =
+					MIN(ui32BytesRemaining, HOST_PAGEALIGN(CpuPAddr.uiAddr) - CpuPAddr.uiAddr);
+			}
+
+			pvCpuVAddr = OSMapPhysToLin(CpuPAddr,
+										ui32BlockBytes,
+										PVRSRV_HAP_KERNEL_ONLY
+										| (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+										IMG_NULL);
+			if(!pvCpuVAddr)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "ZeroBuf: OSMapPhysToLin while zeroing non-contiguous memory FAILED"));
+				return IMG_FALSE;
+			}
+			OSMemSet(pvCpuVAddr, 0, ui32BlockBytes);
+			OSUnMapPhysToLin(pvCpuVAddr,
+							 ui32BlockBytes,
+							 PVRSRV_HAP_KERNEL_ONLY
+							 | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+							 IMG_NULL);
+
+			ui32BytesRemaining -= ui32BlockBytes;
+			ui32CurrentOffset += ui32BlockBytes;
+		}
+	}
+
+	return IMG_TRUE;
+}
+
+static IMG_VOID
+FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator)
+{
+	BM_MAPPING *pMapping;
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			"FreeBuf: pBuf=%08X: DevVAddr=%08X CpuVAddr=%08X CpuPAddr=%08X",
+			pBuf, pBuf->DevVAddr.uiAddr, pBuf->CpuVAddr, pBuf->CpuPAddr.uiAddr));
+
+
+	pMapping = pBuf->pMapping;
+
+	if(ui32Flags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+	{
+		if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+		{
+
+			if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+			{
+
+				PVR_DPF ((PVR_DBG_ERROR, "FreeBuf: combination of DevVAddr management and RAM backing mode unsupported"));
+			}
+			else
+			{
+
+				OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+				pBuf->pMapping = IMG_NULL;
+			}
+		}
+	}
+	else
+	{
+
+		if(pBuf->hOSMemHandle != pMapping->hOSMemHandle)
+		{
+			if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+			{
+
+				OSReleaseSubMemHandle(pBuf->hOSMemHandle, ui32Flags);
+			}
+		}
+		if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+		{
+
+			if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+			{
+
+
+
+				PVR_ASSERT(pBuf->ui32ExportCount == 0);
+				RA_Free (pBuf->pMapping->pArena, pBuf->DevVAddr.uiAddr, IMG_FALSE);
+			}
+		}
+		else
+		{
+			if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+			{
+				switch (pMapping->eCpuMemoryOrigin)
+				{
+					case hm_wrapped:
+						OSUnReservePhys(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+						break;
+					case hm_wrapped_virtaddr:
+						OSUnRegisterMem(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+						break;
+					case hm_wrapped_scatter:
+						OSUnReserveDiscontigPhys(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+						break;
+					case hm_wrapped_scatter_virtaddr:
+						OSUnRegisterDiscontigMem(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+						break;
+					default:
+						break;
+				}
+			}
+
+			if (bFromAllocator)
+				DevMemoryFree (pMapping);
+
+			if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+			{
+
+				OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+				pBuf->pMapping = IMG_NULL;
+			}
+		}
+
+		if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+		{
+			OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf, IMG_NULL);
+
+		}
+	}
+}
+
+PVRSRV_ERROR BM_DestroyContext_AnyCb(BM_HEAP *psBMHeap)
+{
+	if(psBMHeap->ui32Attribs
+	& 	(PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+		|PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+	{
+		if (psBMHeap->pImportArena)
+		{
+			IMG_BOOL bTestDelete = RA_TestDelete(psBMHeap->pImportArena);
+			if (!bTestDelete)
+			{
+				PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext_AnyCb: RA_TestDelete failed"));
+				return PVRSRV_ERROR_GENERIC;
+			}
+		}
+	}
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+BM_DestroyContext(IMG_HANDLE	hBMContext,
+				  IMG_BOOL		*pbDestroyed)
+{
+	PVRSRV_ERROR eError;
+	BM_CONTEXT *pBMContext = (BM_CONTEXT*)hBMContext;
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "BM_DestroyContext"));
+
+	if (pbDestroyed != IMG_NULL)
+	{
+		*pbDestroyed = IMG_FALSE;
+	}
+
+
+
+	if (pBMContext == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Invalid handle"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	pBMContext->ui32RefCount--;
+
+	if (pBMContext->ui32RefCount > 0)
+	{
+
+		return PVRSRV_OK;
+	}
+
+
+
+
+	eError = List_BM_HEAP_PVRSRV_ERROR_Any(pBMContext->psBMHeap, BM_DestroyContext_AnyCb);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: List_BM_HEAP_PVRSRV_ERROR_Any failed"));
+#if 0
+
+
+
+
+		PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Cleaning up with ResManFreeSpecial"));
+		if(ResManFreeSpecial() != PVRSRV_OK)
+		{
+			PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeSpecial failed %d",eError));
+		}
+
+#endif
+		return eError;
+	}
+	else
+	{
+
+		eError = ResManFreeResByPtr(pBMContext->hResItem);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeResByPtr failed %d",eError));
+			return eError;
+		}
+
+
+		if (pbDestroyed != IMG_NULL)
+		{
+			*pbDestroyed = IMG_TRUE;
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR BM_DestroyContextCallBack_AnyVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+
+
+	if(psBMHeap->ui32Attribs
+	& 	(PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+		|PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+	{
+		if (psBMHeap->pImportArena)
+		{
+			RA_Delete (psBMHeap->pImportArena);
+		}
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_DestroyContext: backing store type unsupported"));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+
+	psDeviceNode->pfnMMUDelete(psBMHeap->pMMUHeap);
+
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+
+
+	return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID		pvParam,
+											  IMG_UINT32	ui32Param)
+{
+	BM_CONTEXT *pBMContext = pvParam;
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+
+
+	psDeviceNode = pBMContext->psDeviceNode;
+
+
+
+	if(List_BM_HEAP_PVRSRV_ERROR_Any_va(pBMContext->psBMHeap,
+										BM_DestroyContextCallBack_AnyVaCb,
+										psDeviceNode) != PVRSRV_OK)
+	{
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+
+	if (pBMContext->psMMUContext)
+	{
+		psDeviceNode->pfnMMUFinalise(pBMContext->psMMUContext);
+	}
+
+
+
+	if (pBMContext->pBufferHash)
+	{
+		HASH_Delete(pBMContext->pBufferHash);
+	}
+
+	if (pBMContext == psDeviceNode->sDevMemoryInfo.pBMKernelContext)
+	{
+
+		psDeviceNode->sDevMemoryInfo.pBMKernelContext = IMG_NULL;
+	}
+	else
+	{
+
+		List_BM_CONTEXT_Remove(pBMContext);
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_CONTEXT), pBMContext, IMG_NULL);
+
+
+	return PVRSRV_OK;
+}
+
+
+IMG_HANDLE BM_CreateContext_IncRefCount_AnyVaCb(BM_CONTEXT *pBMContext, va_list va)
+{
+	PRESMAN_CONTEXT	hResManContext;
+	hResManContext = va_arg(va, PRESMAN_CONTEXT);
+	if(ResManFindResourceByPtr(hResManContext, pBMContext->hResItem) == PVRSRV_OK)
+	{
+
+		pBMContext->ui32RefCount++;
+		return pBMContext;
+	}
+	return IMG_NULL;
+}
+
+IMG_VOID BM_CreateContext_InsertHeap_ForEachVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	BM_CONTEXT *pBMContext;
+	psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+	pBMContext = va_arg(va, BM_CONTEXT*);
+	switch(psBMHeap->sDevArena.DevMemHeapType)
+	{
+		case DEVICE_MEMORY_HEAP_SHARED:
+		case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+		{
+
+			psDeviceNode->pfnMMUInsertHeap(pBMContext->psMMUContext, psBMHeap->pMMUHeap);
+			break;
+		}
+	}
+}
+
+IMG_HANDLE
+BM_CreateContext(PVRSRV_DEVICE_NODE			*psDeviceNode,
+				 IMG_DEV_PHYADDR			*psPDDevPAddr,
+				 PVRSRV_PER_PROCESS_DATA	*psPerProc,
+				 IMG_BOOL					*pbCreated)
+{
+	BM_CONTEXT			*pBMContext;
+	DEVICE_MEMORY_INFO	*psDevMemoryInfo;
+	IMG_BOOL			bKernelContext;
+	PRESMAN_CONTEXT		hResManContext;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateContext"));
+
+	if (psPerProc == IMG_NULL)
+	{
+		bKernelContext = IMG_TRUE;
+		hResManContext = psDeviceNode->hResManContext;
+	}
+	else
+	{
+		bKernelContext = IMG_FALSE;
+		hResManContext = psPerProc->hResManContext;
+	}
+
+	if (pbCreated != IMG_NULL)
+	{
+		*pbCreated = IMG_FALSE;
+	}
+
+
+	psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+	if (bKernelContext == IMG_FALSE)
+	{
+		IMG_HANDLE res = (IMG_HANDLE) List_BM_CONTEXT_Any_va(psDevMemoryInfo->pBMContext,
+															BM_CreateContext_IncRefCount_AnyVaCb,
+															hResManContext);
+		if (res)
+		{
+			return res;
+		}
+	}
+
+
+	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof (struct _BM_CONTEXT_),
+					 (IMG_PVOID *)&pBMContext, IMG_NULL,
+					 "Buffer Manager Context") != PVRSRV_OK)
+	{
+		PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: Alloc failed"));
+		return IMG_NULL;
+	}
+	OSMemSet(pBMContext, 0, sizeof (BM_CONTEXT));
+
+
+	pBMContext->psDeviceNode = psDeviceNode;
+
+
+
+	pBMContext->pBufferHash = HASH_Create(32);
+	if (pBMContext->pBufferHash==IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: HASH_Create failed"));
+		goto cleanup;
+	}
+
+	if(psDeviceNode->pfnMMUInitialise(psDeviceNode,
+										&pBMContext->psMMUContext,
+										psPDDevPAddr) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_CreateContext: MMUInitialise failed"));
+		goto cleanup;
+	}
+
+	if(bKernelContext)
+	{
+
+		PVR_ASSERT(psDevMemoryInfo->pBMKernelContext == IMG_NULL);
+		psDevMemoryInfo->pBMKernelContext = pBMContext;
+	}
+	else
+	{
+
+
+
+
+
+		PVR_ASSERT(psDevMemoryInfo->pBMKernelContext);
+
+		if (psDevMemoryInfo->pBMKernelContext == IMG_NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "BM_CreateContext: psDevMemoryInfo->pBMKernelContext invalid"));
+			goto cleanup;
+		}
+
+		PVR_ASSERT(psDevMemoryInfo->pBMKernelContext->psBMHeap);
+
+
+
+
+
+		pBMContext->psBMSharedHeap = psDevMemoryInfo->pBMKernelContext->psBMHeap;
+
+
+
+
+		List_BM_HEAP_ForEach_va(pBMContext->psBMSharedHeap,
+								BM_CreateContext_InsertHeap_ForEachVaCb,
+								psDeviceNode,
+								pBMContext);
+
+
+		List_BM_CONTEXT_Insert(&psDevMemoryInfo->pBMContext, pBMContext);
+	}
+
+
+	pBMContext->ui32RefCount++;
+
+
+	pBMContext->hResItem = ResManRegisterRes(hResManContext,
+											RESMAN_TYPE_DEVICEMEM_CONTEXT,
+											pBMContext,
+											0,
+											BM_DestroyContextCallBack);
+	if (pBMContext->hResItem == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: ResManRegisterRes failed"));
+		goto cleanup;
+	}
+
+	if (pbCreated != IMG_NULL)
+	{
+		*pbCreated = IMG_TRUE;
+	}
+	return (IMG_HANDLE)pBMContext;
+
+cleanup:
+	(IMG_VOID)BM_DestroyContextCallBack(pBMContext, 0);
+
+	return IMG_NULL;
+}
+
+
+IMG_VOID *BM_CreateHeap_AnyVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+	DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo;
+	psDevMemHeapInfo = va_arg(va, DEVICE_MEMORY_HEAP_INFO*);
+	if (psBMHeap->sDevArena.ui32HeapID ==  psDevMemHeapInfo->ui32HeapID)
+	{
+
+		return psBMHeap;
+	}
+	else
+	{
+		return IMG_NULL;
+	}
+}
+
+IMG_HANDLE
+BM_CreateHeap (IMG_HANDLE hBMContext,
+			   DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo)
+{
+	BM_CONTEXT *pBMContext = (BM_CONTEXT*)hBMContext;
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	BM_HEAP *psBMHeap;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateHeap"));
+
+	if(!pBMContext)
+	{
+		return IMG_NULL;
+	}
+
+	psDeviceNode = pBMContext->psDeviceNode;
+
+
+
+
+
+
+	if(pBMContext->ui32RefCount > 0)
+	{
+		psBMHeap = (BM_HEAP*)List_BM_HEAP_Any_va(pBMContext->psBMHeap,
+												 BM_CreateHeap_AnyVaCb,
+												 psDevMemHeapInfo);
+
+		if (psBMHeap)
+		{
+			return psBMHeap;
+		}
+	}
+
+
+	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof (BM_HEAP),
+						(IMG_PVOID *)&psBMHeap, IMG_NULL,
+						"Buffer Manager Heap") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: Alloc failed"));
+		return IMG_NULL;
+	}
+
+	OSMemSet (psBMHeap, 0, sizeof (BM_HEAP));
+
+	psBMHeap->sDevArena.ui32HeapID = psDevMemHeapInfo->ui32HeapID;
+	psBMHeap->sDevArena.pszName = psDevMemHeapInfo->pszName;
+	psBMHeap->sDevArena.BaseDevVAddr = psDevMemHeapInfo->sDevVAddrBase;
+	psBMHeap->sDevArena.ui32Size = psDevMemHeapInfo->ui32HeapSize;
+	psBMHeap->sDevArena.DevMemHeapType = psDevMemHeapInfo->DevMemHeapType;
+	psBMHeap->sDevArena.ui32DataPageSize = psDevMemHeapInfo->ui32DataPageSize;
+	psBMHeap->sDevArena.psDeviceMemoryHeapInfo = psDevMemHeapInfo;
+	psBMHeap->ui32Attribs = psDevMemHeapInfo->ui32Attribs;
+
+
+	psBMHeap->pBMContext = pBMContext;
+
+	psBMHeap->pMMUHeap = psDeviceNode->pfnMMUCreate (pBMContext->psMMUContext,
+													&psBMHeap->sDevArena,
+													&psBMHeap->pVMArena);
+	if (!psBMHeap->pMMUHeap)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: MMUCreate failed"));
+		goto ErrorExit;
+	}
+
+
+	psBMHeap->pImportArena = RA_Create (psDevMemHeapInfo->pszBSName,
+										0, 0, IMG_NULL,
+										psBMHeap->sDevArena.ui32DataPageSize,
+										BM_ImportMemory,
+										BM_FreeMemory,
+										IMG_NULL,
+										psBMHeap);
+	if(psBMHeap->pImportArena == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: RA_Create failed"));
+		goto ErrorExit;
+	}
+
+	if(psBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+	{
+
+
+
+
+		psBMHeap->pLocalDevMemArena = psDevMemHeapInfo->psLocalDevMemArena;
+		if(psBMHeap->pLocalDevMemArena == IMG_NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: LocalDevMemArena null"));
+			goto ErrorExit;
+		}
+	}
+
+
+	List_BM_HEAP_Insert(&pBMContext->psBMHeap, psBMHeap);
+
+	return (IMG_HANDLE)psBMHeap;
+
+
+ErrorExit:
+
+
+	if (psBMHeap->pMMUHeap != IMG_NULL)
+	{
+		psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap);
+		psDeviceNode->pfnMMUFinalise (pBMContext->psMMUContext);
+	}
+
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+
+
+	return IMG_NULL;
+}
+
+IMG_VOID
+BM_DestroyHeap (IMG_HANDLE hDevMemHeap)
+{
+	BM_HEAP* psBMHeap = (BM_HEAP*)hDevMemHeap;
+	PVRSRV_DEVICE_NODE *psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "BM_DestroyHeap"));
+
+	if(psBMHeap)
+	{
+
+		if(psBMHeap->ui32Attribs
+		&	(PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+			|PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+		{
+			if (psBMHeap->pImportArena)
+			{
+				RA_Delete (psBMHeap->pImportArena);
+			}
+		}
+		else
+		{
+			PVR_DPF((PVR_DBG_ERROR, "BM_DestroyHeap: backing store type unsupported"));
+			return;
+		}
+
+
+		psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap);
+
+
+		List_BM_HEAP_Remove(psBMHeap);
+
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+
+	}
+	else
+	{
+		PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyHeap: invalid heap handle"));
+	}
+}
+
+
+IMG_BOOL
+BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+
+	PVR_DPF((PVR_DBG_MESSAGE, "BM_Reinitialise"));
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+
+	return IMG_TRUE;
+}
+
+IMG_BOOL
+BM_Alloc (  IMG_HANDLE			hDevMemHeap,
+			IMG_DEV_VIRTADDR	*psDevVAddr,
+			IMG_SIZE_T			uSize,
+			IMG_UINT32			*pui32Flags,
+			IMG_UINT32			uDevVAddrAlignment,
+			BM_HANDLE			*phBuf)
+{
+	BM_BUF *pBuf;
+	BM_CONTEXT *pBMContext;
+	BM_HEAP *psBMHeap;
+	SYS_DATA *psSysData;
+	IMG_UINT32 uFlags;
+
+	if (pui32Flags == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: invalid parameter"));
+		PVR_DBG_BREAK;
+		return IMG_FALSE;
+	}
+
+	uFlags = *pui32Flags;
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+		  "BM_Alloc (uSize=0x%x, uFlags=0x%x, uDevVAddrAlignment=0x%x)",
+			uSize, uFlags, uDevVAddrAlignment));
+
+	SysAcquireData(&psSysData);
+
+	psBMHeap = (BM_HEAP*)hDevMemHeap;
+	pBMContext = psBMHeap->pBMContext;
+
+	if(uDevVAddrAlignment == 0)
+	{
+		uDevVAddrAlignment = 1;
+	}
+
+
+	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				   sizeof (BM_BUF),
+				   (IMG_PVOID *)&pBuf, IMG_NULL,
+				   "Buffer Manager buffer") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: BM_Buf alloc FAILED"));
+		return IMG_FALSE;
+	}
+	OSMemSet(pBuf, 0, sizeof (BM_BUF));
+
+
+	if (AllocMemory(pBMContext,
+					psBMHeap,
+					psDevVAddr,
+					uSize,
+					uFlags,
+					uDevVAddrAlignment,
+					pBuf) != IMG_TRUE)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL);
+
+		PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: AllocMemory FAILED"));
+		return IMG_FALSE;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+		  "BM_Alloc (uSize=0x%x, uFlags=0x%x)=%08X",
+		  uSize, uFlags, pBuf));
+
+
+	pBuf->ui32RefCount = 1;
+	*phBuf = (BM_HANDLE)pBuf;
+	*pui32Flags = uFlags | psBMHeap->ui32Attribs;
+
+
+	if(uFlags & PVRSRV_HAP_CACHETYPE_MASK)
+	{
+		*pui32Flags &= ~PVRSRV_HAP_CACHETYPE_MASK;
+		*pui32Flags |= (uFlags & PVRSRV_HAP_CACHETYPE_MASK);
+	}
+
+	return IMG_TRUE;
+}
+
+
+
+#if defined(PVR_LMA)
+static IMG_BOOL
+ValidSysPAddrArrayForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR *psSysPAddr, IMG_UINT32 ui32PageCount, IMG_SIZE_T ui32PageSize)
+{
+	IMG_UINT32 i;
+
+	for (i = 0; i < ui32PageCount; i++)
+	{
+		IMG_SYS_PHYADDR sStartSysPAddr = psSysPAddr[i];
+		IMG_SYS_PHYADDR sEndSysPAddr;
+
+		if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sStartSysPAddr))
+		{
+			return IMG_FALSE;
+		}
+
+		sEndSysPAddr.uiAddr = sStartSysPAddr.uiAddr + ui32PageSize;
+
+		if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sEndSysPAddr))
+		{
+			return IMG_FALSE;
+		}
+	}
+
+	return IMG_TRUE;
+}
+
+static IMG_BOOL
+ValidSysPAddrRangeForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR sStartSysPAddr, IMG_SIZE_T ui32Range)
+{
+	IMG_SYS_PHYADDR sEndSysPAddr;
+
+	if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sStartSysPAddr))
+	{
+		return IMG_FALSE;
+	}
+
+	sEndSysPAddr.uiAddr = sStartSysPAddr.uiAddr + ui32Range;
+
+	if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sEndSysPAddr))
+	{
+		return IMG_FALSE;
+	}
+
+	return IMG_TRUE;
+}
+
+#define	WRAP_MAPPING_SIZE(ui32ByteSize, ui32PageOffset) HOST_PAGEALIGN((ui32ByteSize) + (ui32PageOffset))
+
+#define	WRAP_PAGE_COUNT(ui32ByteSize, ui32PageOffset, ui32HostPageSize)	(WRAP_MAPPING_SIZE(ui32ByteSize, ui32PageOffset) / (ui32HostPageSize))
+
+#endif
+
+
+IMG_BOOL
+BM_Wrap (	IMG_HANDLE hDevMemHeap,
+			IMG_SIZE_T ui32Size,
+			IMG_SIZE_T ui32Offset,
+			IMG_BOOL bPhysContig,
+			IMG_SYS_PHYADDR *psSysAddr,
+			IMG_VOID *pvCPUVAddr,
+			IMG_UINT32 *pui32Flags,
+			BM_HANDLE *phBuf)
+{
+	BM_BUF *pBuf;
+	BM_CONTEXT *psBMContext;
+	BM_HEAP *psBMHeap;
+	SYS_DATA *psSysData;
+	IMG_SYS_PHYADDR sHashAddress;
+	IMG_UINT32 uFlags;
+
+	psBMHeap = (BM_HEAP*)hDevMemHeap;
+	psBMContext = psBMHeap->pBMContext;
+
+	uFlags = psBMHeap->ui32Attribs & (PVRSRV_HAP_CACHETYPE_MASK | PVRSRV_HAP_MAPTYPE_MASK);
+
+	if ((pui32Flags != IMG_NULL) && ((*pui32Flags & PVRSRV_HAP_CACHETYPE_MASK) != 0))
+	{
+		uFlags &= ~PVRSRV_HAP_CACHETYPE_MASK;
+		uFlags |= *pui32Flags & PVRSRV_HAP_CACHETYPE_MASK;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+		  "BM_Wrap (uSize=0x%x, uOffset=0x%x, bPhysContig=0x%x, pvCPUVAddr=0x%x, uFlags=0x%x)",
+			ui32Size, ui32Offset, bPhysContig, pvCPUVAddr, uFlags));
+
+	SysAcquireData(&psSysData);
+
+#if defined(PVR_LMA)
+	if (bPhysContig)
+	{
+		if (!ValidSysPAddrRangeForDev(psBMContext->psDeviceNode, *psSysAddr, WRAP_MAPPING_SIZE(ui32Size, ui32Offset)))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: System address range invalid for device"));
+			return IMG_FALSE;
+		}
+	}
+	else
+	{
+		IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE();
+
+		if (!ValidSysPAddrArrayForDev(psBMContext->psDeviceNode, psSysAddr, WRAP_PAGE_COUNT(ui32Size, ui32Offset, ui32HostPageSize), ui32HostPageSize))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: Array of system addresses invalid for device"));
+			return IMG_FALSE;
+		}
+	}
+#endif
+
+	sHashAddress = psSysAddr[0];
+
+
+	sHashAddress.uiAddr += ui32Offset;
+
+
+	pBuf = (BM_BUF *)HASH_Retrieve(psBMContext->pBufferHash, (IMG_UINTPTR_T) sHashAddress.uiAddr);
+
+	if(pBuf)
+	{
+		IMG_SIZE_T ui32MappingSize = HOST_PAGEALIGN (ui32Size + ui32Offset);
+
+
+		if(pBuf->pMapping->uSize == ui32MappingSize && (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped ||
+														pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr))
+		{
+			PVR_DPF((PVR_DBG_MESSAGE,
+					"BM_Wrap (Matched previous Wrap! uSize=0x%x, uOffset=0x%x, SysAddr=%08X)",
+					ui32Size, ui32Offset, sHashAddress.uiAddr));
+
+			pBuf->ui32RefCount++;
+			*phBuf = (BM_HANDLE)pBuf;
+			if(pui32Flags)
+				*pui32Flags = uFlags;
+
+			return IMG_TRUE;
+		}
+	}
+
+
+	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof (BM_BUF),
+						(IMG_PVOID *)&pBuf, IMG_NULL,
+						"Buffer Manager buffer") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: BM_Buf alloc FAILED"));
+		return IMG_FALSE;
+	}
+	OSMemSet(pBuf, 0, sizeof (BM_BUF));
+
+
+	if (WrapMemory (psBMHeap, ui32Size, ui32Offset, bPhysContig, psSysAddr, pvCPUVAddr, uFlags, pBuf) != IMG_TRUE)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: WrapMemory FAILED"));
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL);
+
+		return IMG_FALSE;
+	}
+
+
+	if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)
+	{
+
+		PVR_ASSERT(SysSysPAddrToCpuPAddr(sHashAddress).uiAddr == pBuf->CpuPAddr.uiAddr);
+
+		if (!HASH_Insert (psBMContext->pBufferHash, (IMG_UINTPTR_T) sHashAddress.uiAddr, (IMG_UINTPTR_T)pBuf))
+		{
+			FreeBuf (pBuf, uFlags, IMG_TRUE);
+			PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: HASH_Insert FAILED"));
+			return IMG_FALSE;
+		}
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			"BM_Wrap (uSize=0x%x, uFlags=0x%x)=%08X(devVAddr=%08X)",
+			ui32Size, uFlags, pBuf, pBuf->DevVAddr.uiAddr));
+
+
+	pBuf->ui32RefCount = 1;
+	*phBuf = (BM_HANDLE)pBuf;
+	if(pui32Flags)
+	{
+
+		*pui32Flags = (uFlags & ~PVRSRV_HAP_MAPTYPE_MASK) | PVRSRV_HAP_MULTI_PROCESS;
+	}
+
+	return IMG_TRUE;
+}
+
+
+IMG_VOID BM_Export (BM_HANDLE hBuf)
+{
+	BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+	pBuf->ui32ExportCount++;
+}
+
+IMG_VOID BM_FreeExport (BM_HANDLE hBuf, IMG_UINT32 ui32Flags)
+{
+	BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+	pBuf->ui32ExportCount--;
+	FreeBuf (pBuf, ui32Flags, IMG_FALSE);
+}
+
+IMG_VOID
+BM_Free (BM_HANDLE hBuf,
+		IMG_UINT32 ui32Flags)
+{
+	BM_BUF *pBuf = (BM_BUF *)hBuf;
+	SYS_DATA *psSysData;
+	IMG_SYS_PHYADDR sHashAddr;
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "BM_Free (h=%08X)", hBuf));
+	PVR_ASSERT (pBuf!=IMG_NULL);
+
+	if (pBuf == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_Free: invalid parameter"));
+		return;
+	}
+
+	SysAcquireData(&psSysData);
+
+	pBuf->ui32RefCount--;
+
+	if(pBuf->ui32RefCount == 0)
+	{
+		if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)
+		{
+			sHashAddr = SysCpuPAddrToSysPAddr(pBuf->CpuPAddr);
+
+			HASH_Remove (pBuf->pMapping->pBMHeap->pBMContext->pBufferHash,	(IMG_UINTPTR_T)sHashAddr.uiAddr);
+		}
+		FreeBuf (pBuf, ui32Flags, IMG_TRUE);
+	}
+}
+
+
+IMG_CPU_VIRTADDR
+BM_HandleToCpuVaddr (BM_HANDLE hBuf)
+{
+	BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+	PVR_ASSERT (pBuf != IMG_NULL);
+	if (pBuf == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_HandleToCpuVaddr: invalid parameter"));
+		return IMG_NULL;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+				"BM_HandleToCpuVaddr(h=%08X)=%08X",
+				hBuf, pBuf->CpuVAddr));
+	return pBuf->CpuVAddr;
+}
+
+
+IMG_DEV_VIRTADDR
+BM_HandleToDevVaddr (BM_HANDLE hBuf)
+{
+	BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+	PVR_ASSERT (pBuf != IMG_NULL);
+	if (pBuf == IMG_NULL)
+	{
+		IMG_DEV_VIRTADDR	DevVAddr = {0};
+		PVR_DPF((PVR_DBG_ERROR, "BM_HandleToDevVaddr: invalid parameter"));
+		return DevVAddr;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "BM_HandleToDevVaddr(h=%08X)=%08X", hBuf, pBuf->DevVAddr));
+	return pBuf->DevVAddr;
+}
+
+
+IMG_SYS_PHYADDR
+BM_HandleToSysPaddr (BM_HANDLE hBuf)
+{
+	BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+	PVR_ASSERT (pBuf != IMG_NULL);
+
+	if (pBuf == IMG_NULL)
+	{
+		IMG_SYS_PHYADDR	PhysAddr = {0};
+		PVR_DPF((PVR_DBG_ERROR, "BM_HandleToSysPaddr: invalid parameter"));
+		return PhysAddr;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "BM_HandleToSysPaddr(h=%08X)=%08X", hBuf, pBuf->CpuPAddr.uiAddr));
+	return SysCpuPAddrToSysPAddr (pBuf->CpuPAddr);
+}
+
+IMG_HANDLE
+BM_HandleToOSMemHandle(BM_HANDLE hBuf)
+{
+	BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+	PVR_ASSERT (pBuf != IMG_NULL);
+
+	if (pBuf == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_HandleToOSMemHandle: invalid parameter"));
+		return IMG_NULL;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+				"BM_HandleToOSMemHandle(h=%08X)=%08X",
+				hBuf, pBuf->hOSMemHandle));
+	return pBuf->hOSMemHandle;
+}
+
+IMG_BOOL
+BM_ContiguousStatistics (IMG_UINT32 uFlags,
+						 IMG_UINT32 *pTotalBytes,
+						 IMG_UINT32 *pAvailableBytes)
+{
+	if (pAvailableBytes || pTotalBytes || uFlags);
+	return IMG_FALSE;
+}
+
+
+static IMG_BOOL
+DevMemoryAlloc (BM_CONTEXT *pBMContext,
+				BM_MAPPING *pMapping,
+				IMG_SIZE_T *pActualSize,
+				IMG_UINT32 uFlags,
+				IMG_UINT32 dev_vaddr_alignment,
+				IMG_DEV_VIRTADDR *pDevVAddr)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+#ifdef PDUMP
+	IMG_UINT32 ui32PDumpSize = pMapping->uSize;
+#endif
+
+	psDeviceNode = pBMContext->psDeviceNode;
+
+	if(uFlags & PVRSRV_MEM_INTERLEAVED)
+	{
+
+		pMapping->uSize *= 2;
+	}
+
+#ifdef PDUMP
+	if(uFlags & PVRSRV_MEM_DUMMY)
+	{
+
+		ui32PDumpSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
+	}
+#endif
+
+
+	if (!psDeviceNode->pfnMMUAlloc (pMapping->pBMHeap->pMMUHeap,
+									pMapping->uSize,
+									pActualSize,
+									0,
+									dev_vaddr_alignment,
+									&(pMapping->DevVAddr)))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "DevMemoryAlloc ERROR MMU_Alloc"));
+		return IMG_FALSE;
+	}
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+	EnableHostAccess(pBMContext->psMMUContext);
+#endif
+
+
+
+	PDUMPMALLOCPAGES(psDeviceNode->sDevId.eDeviceType, pMapping->DevVAddr.uiAddr, pMapping->CpuVAddr, pMapping->hOSMemHandle, ui32PDumpSize, pMapping->pBMHeap->sDevArena.ui32DataPageSize, (IMG_HANDLE)pMapping);
+
+	switch (pMapping->eCpuMemoryOrigin)
+	{
+		case hm_wrapped:
+		case hm_wrapped_virtaddr:
+		case hm_contiguous:
+		{
+			psDeviceNode->pfnMMUMapPages (	pMapping->pBMHeap->pMMUHeap,
+							pMapping->DevVAddr,
+							SysCpuPAddrToSysPAddr (pMapping->CpuPAddr),
+							pMapping->uSize,
+							uFlags,
+							(IMG_HANDLE)pMapping);
+
+			*pDevVAddr = pMapping->DevVAddr;
+			break;
+		}
+		case hm_env:
+		{
+			psDeviceNode->pfnMMUMapShadow (	pMapping->pBMHeap->pMMUHeap,
+							pMapping->DevVAddr,
+							pMapping->uSize,
+							pMapping->CpuVAddr,
+							pMapping->hOSMemHandle,
+							pDevVAddr,
+							uFlags,
+							(IMG_HANDLE)pMapping);
+			break;
+		}
+		case hm_wrapped_scatter:
+		case hm_wrapped_scatter_virtaddr:
+		{
+			psDeviceNode->pfnMMUMapScatter (pMapping->pBMHeap->pMMUHeap,
+							pMapping->DevVAddr,
+							pMapping->psSysAddr,
+							pMapping->uSize,
+							uFlags,
+							(IMG_HANDLE)pMapping);
+
+			*pDevVAddr = pMapping->DevVAddr;
+			break;
+		}
+		default:
+			PVR_DPF((PVR_DBG_ERROR,
+				"Illegal value %d for pMapping->eCpuMemoryOrigin",
+				pMapping->eCpuMemoryOrigin));
+			return IMG_FALSE;
+	}
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+	DisableHostAccess(pBMContext->psMMUContext);
+#endif
+
+	return IMG_TRUE;
+}
+
+static IMG_VOID
+DevMemoryFree (BM_MAPPING *pMapping)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+#ifdef PDUMP
+	IMG_UINT32 ui32PSize;
+#endif
+
+#ifdef PDUMP
+
+	if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+	{
+
+		ui32PSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
+	}
+	else
+	{
+		ui32PSize = pMapping->uSize;
+	}
+
+	PDUMPFREEPAGES(pMapping->pBMHeap,
+                    pMapping->DevVAddr,
+                    ui32PSize,
+                    pMapping->pBMHeap->sDevArena.ui32DataPageSize,
+                    (IMG_HANDLE)pMapping,
+                    (pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) ? IMG_TRUE : IMG_FALSE);
+#endif
+
+	psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+	psDeviceNode->pfnMMUFree (pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr, IMG_CAST_TO_DEVVADDR_UINT(pMapping->uSize));
+}
+
+static IMG_BOOL
+BM_ImportMemory (IMG_VOID *pH,
+			  IMG_SIZE_T uRequestSize,
+			  IMG_SIZE_T *pActualSize,
+			  BM_MAPPING **ppsMapping,
+			  IMG_UINT32 uFlags,
+			  IMG_UINTPTR_T *pBase)
+{
+	BM_MAPPING *pMapping;
+	BM_HEAP *pBMHeap = pH;
+	BM_CONTEXT *pBMContext = pBMHeap->pBMContext;
+	IMG_BOOL bResult;
+	IMG_SIZE_T uSize;
+	IMG_SIZE_T uPSize;
+	IMG_UINT32 uDevVAddrAlignment = 0;
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "BM_ImportMemory (pBMContext=%08X, uRequestSize=0x%x, uFlags=0x%x, uAlign=0x%x)",
+			  pBMContext, uRequestSize, uFlags, uDevVAddrAlignment));
+
+	PVR_ASSERT (ppsMapping != IMG_NULL);
+	PVR_ASSERT (pBMContext != IMG_NULL);
+
+	if (ppsMapping == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: invalid parameter"));
+		goto fail_exit;
+	}
+
+	uSize = HOST_PAGEALIGN (uRequestSize);
+	PVR_ASSERT (uSize >= uRequestSize);
+
+	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof (BM_MAPPING),
+						(IMG_PVOID *)&pMapping, IMG_NULL,
+						"Buffer Manager Mapping") != PVRSRV_OK)
+	{
+		PVR_DPF ((PVR_DBG_ERROR, "BM_ImportMemory: failed BM_MAPPING alloc"));
+		goto fail_exit;
+	}
+
+	pMapping->hOSMemHandle = 0;
+	pMapping->CpuVAddr = 0;
+	pMapping->DevVAddr.uiAddr = 0;
+	pMapping->CpuPAddr.uiAddr = 0;
+	pMapping->uSize = uSize;
+	pMapping->pBMHeap = pBMHeap;
+	pMapping->ui32Flags = uFlags;
+
+
+	if (pActualSize)
+	{
+		*pActualSize = uSize;
+	}
+
+
+	if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+	{
+		uPSize = pBMHeap->sDevArena.ui32DataPageSize;
+	}
+	else
+	{
+		uPSize = pMapping->uSize;
+	}
+
+
+
+	if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+	{
+		IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs;
+
+
+		if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+		{
+			ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+			ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+		}
+
+
+		if (OSAllocPages(ui32Attribs,
+						 uPSize,
+						 pBMHeap->sDevArena.ui32DataPageSize,
+						 (IMG_VOID **)&pMapping->CpuVAddr,
+						 &pMapping->hOSMemHandle) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					"BM_ImportMemory: OSAllocPages(0x%x) failed",
+					uPSize));
+			goto fail_mapping_alloc;
+		}
+
+
+		pMapping->eCpuMemoryOrigin = hm_env;
+	}
+	else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+	{
+		IMG_SYS_PHYADDR sSysPAddr;
+		IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs;
+
+
+		if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+		{
+			ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+			ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+		}
+
+
+		PVR_ASSERT(pBMHeap->pLocalDevMemArena != IMG_NULL);
+
+		if (!RA_Alloc (pBMHeap->pLocalDevMemArena,
+					   uPSize,
+					   IMG_NULL,
+					   IMG_NULL,
+					   0,
+					   pBMHeap->sDevArena.ui32DataPageSize,
+					   0,
+					   (IMG_UINTPTR_T *)&sSysPAddr.uiAddr))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: RA_Alloc(0x%x) FAILED", uPSize));
+			goto fail_mapping_alloc;
+		}
+
+
+		pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+		if(OSReservePhys(pMapping->CpuPAddr,
+						 uPSize,
+						 ui32Attribs,
+						 &pMapping->CpuVAddr,
+						 &pMapping->hOSMemHandle) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,	"BM_ImportMemory: OSReservePhys failed"));
+			goto fail_dev_mem_alloc;
+		}
+
+
+		pMapping->eCpuMemoryOrigin = hm_contiguous;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR,	"BM_ImportMemory: Invalid backing store type"));
+		goto fail_mapping_alloc;
+	}
+
+
+	bResult = DevMemoryAlloc (pBMContext,
+								pMapping,
+								IMG_NULL,
+								uFlags,
+								uDevVAddrAlignment,
+								&pMapping->DevVAddr);
+	if (!bResult)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"BM_ImportMemory: DevMemoryAlloc(0x%x) failed",
+				pMapping->uSize));
+		goto fail_dev_mem_alloc;
+	}
+
+
+
+	PVR_ASSERT (uDevVAddrAlignment>1?(pMapping->DevVAddr.uiAddr%uDevVAddrAlignment)==0:1);
+
+	*pBase = pMapping->DevVAddr.uiAddr;
+	*ppsMapping = pMapping;
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "BM_ImportMemory: IMG_TRUE"));
+	return IMG_TRUE;
+
+fail_dev_mem_alloc:
+	if (pMapping && (pMapping->CpuVAddr || pMapping->hOSMemHandle))
+	{
+
+		if(pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED)
+		{
+			pMapping->uSize /= 2;
+		}
+
+		if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+		{
+			uPSize = pBMHeap->sDevArena.ui32DataPageSize;
+		}
+		else
+		{
+			uPSize = pMapping->uSize;
+		}
+
+		if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+		{
+			OSFreePages(pBMHeap->ui32Attribs,
+						  uPSize,
+						  (IMG_VOID *)pMapping->CpuVAddr,
+						  pMapping->hOSMemHandle);
+		}
+		else
+		{
+			IMG_SYS_PHYADDR sSysPAddr;
+
+			if(pMapping->CpuVAddr)
+			{
+				OSUnReservePhys(pMapping->CpuVAddr,
+								uPSize,
+								pBMHeap->ui32Attribs,
+								pMapping->hOSMemHandle);
+			}
+			sSysPAddr = SysCpuPAddrToSysPAddr(pMapping->CpuPAddr);
+			RA_Free (pBMHeap->pLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+		}
+	}
+fail_mapping_alloc:
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+
+fail_exit:
+	return IMG_FALSE;
+}
+
+
+static IMG_VOID
+BM_FreeMemory (IMG_VOID *h, IMG_UINTPTR_T _base, BM_MAPPING *psMapping)
+{
+	BM_HEAP *pBMHeap = h;
+	IMG_SIZE_T uPSize;
+
+	PVR_UNREFERENCED_PARAMETER (_base);
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "BM_FreeMemory (h=%08X, base=0x%x, psMapping=0x%x)", h, _base, psMapping));
+
+	PVR_ASSERT (psMapping != IMG_NULL);
+
+	if (psMapping == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_FreeMemory: invalid parameter"));
+		return;
+	}
+
+	DevMemoryFree (psMapping);
+
+
+	if((psMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) != 0)
+	{
+		psMapping->uSize /= 2;
+	}
+
+	if(psMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+	{
+		uPSize = psMapping->pBMHeap->sDevArena.ui32DataPageSize;
+	}
+	else
+	{
+		uPSize = psMapping->uSize;
+	}
+
+	if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+	{
+		OSFreePages(pBMHeap->ui32Attribs,
+						uPSize,
+						(IMG_VOID *) psMapping->CpuVAddr,
+						psMapping->hOSMemHandle);
+	}
+	else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+	{
+		IMG_SYS_PHYADDR sSysPAddr;
+
+		OSUnReservePhys(psMapping->CpuVAddr, uPSize, pBMHeap->ui32Attribs, psMapping->hOSMemHandle);
+
+		sSysPAddr = SysCpuPAddrToSysPAddr(psMapping->CpuPAddr);
+
+		RA_Free (pBMHeap->pLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR,	"BM_FreeMemory: Invalid backing store type"));
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), psMapping, IMG_NULL);
+
+
+	PVR_DPF((PVR_DBG_MESSAGE,
+			"..BM_FreeMemory (h=%08X, base=0x%x, psMapping=0x%x)",
+			h, _base, psMapping));
+}
+
+IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+								IMG_DEV_VIRTADDR sDevVPageAddr,
+								IMG_DEV_PHYADDR *psDevPAddr)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "BM_GetPhysPageAddr"));
+
+	PVR_ASSERT (psMemInfo && psDevPAddr)
+
+
+	PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+	psDeviceNode = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+	*psDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pMMUHeap,
+												sDevVPageAddr);
+}
+
+
+PVRSRV_ERROR BM_GetHeapInfo(IMG_HANDLE hDevMemHeap, PVRSRV_HEAP_INFO *psHeapInfo)
+{
+	BM_HEAP *psBMHeap = (BM_HEAP *)hDevMemHeap;
+
+	PVR_DPF((PVR_DBG_VERBOSE, "BM_GetHeapInfo"));
+
+	psHeapInfo->hDevMemHeap = hDevMemHeap;
+	psHeapInfo->sDevVAddrBase = psBMHeap->sDevArena.BaseDevVAddr;
+	psHeapInfo->ui32HeapByteSize = psBMHeap->sDevArena.ui32Size;
+	psHeapInfo->ui32Attribs = psBMHeap->ui32Attribs;
+
+	return PVRSRV_OK;
+}
+
+
+MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap)
+{
+	BM_HEAP *pBMHeap = (BM_HEAP*)hDevMemHeap;
+
+	PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUContext"));
+
+	return pBMHeap->pBMContext->psMMUContext;
+}
+
+MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext)
+{
+	BM_CONTEXT *pBMContext = (BM_CONTEXT*)hDevMemContext;
+
+	PVR_DPF ((PVR_DBG_VERBOSE, "BM_GetMMUContextFromMemContext"));
+
+	return pBMContext->psMMUContext;
+}
+
+IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap)
+{
+	PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUHeap"));
+
+	return (IMG_HANDLE)((BM_HEAP*)hDevMemHeap)->pMMUHeap;
+}
+
+
+PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext)
+{
+	PVR_DPF((PVR_DBG_VERBOSE, "BM_GetDeviceNode"));
+
+	return ((BM_CONTEXT*)hDevMemContext)->psDeviceNode;
+}
+
+
+IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+	PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMappingHandle"));
+
+	return ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->hOSMemHandle;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/deviceclass.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/deviceclass.c
new file mode 100644
index 0000000..2867a08
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/deviceclass.c
@@ -0,0 +1,2060 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "kernelbuffer.h"
+#include "pvr_bridge_km.h"
+
+#include "lists.h"
+#include "emgd_drm.h"
+
+DECLARE_LIST_ANY_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_INSERT(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_REMOVE(PVRSRV_DEVICE_NODE);
+
+IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va);
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID);
+PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID);
+
+#if defined(SUPPORT_MISR_IN_THREAD)
+void OSVSyncMISR(IMG_HANDLE, IMG_BOOL);
+#endif
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE	hCmdCookie,
+										   IMG_BOOL		bScheduleMISR);
+#endif
+typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG *PPVRSRV_DC_SRV2DISP_KMJTABLE;
+
+typedef struct PVRSRV_DC_BUFFER_TAG
+{
+
+	PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
+
+	struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
+	struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
+} PVRSRV_DC_BUFFER;
+
+typedef struct PVRSRV_DC_SWAPCHAIN_TAG
+{
+	IMG_HANDLE							hExtSwapChain;
+	IMG_UINT32							ui32SwapChainID;
+	IMG_UINT32							ui32Flags;
+	IMG_UINT32							ui32RefCount;
+	PVRSRV_QUEUE_INFO					*psQueue;
+	PVRSRV_DC_BUFFER					asBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+	IMG_UINT32							ui32BufferCount;
+	PVRSRV_DC_BUFFER					*psLastFlipBuffer;
+	struct PVRSRV_DC_SWAPCHAIN_TAG		*psNext;
+	struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
+} PVRSRV_DC_SWAPCHAIN;
+
+typedef struct PVRSRV_DC_SWAPCHAIN_REF_TAG
+{
+	struct PVRSRV_DC_SWAPCHAIN_TAG		*psSwapChain;
+	IMG_HANDLE							hResItem;
+} PVRSRV_DC_SWAPCHAIN_REF;
+
+
+typedef struct PVRSRV_DISPLAYCLASS_INFO_TAG
+{
+	IMG_UINT32 							ui32RefCount;
+	IMG_UINT32							ui32DeviceID;
+	IMG_HANDLE							hExtDevice;
+	PPVRSRV_DC_SRV2DISP_KMJTABLE		psFuncTable;
+	IMG_HANDLE							hDevMemContext;
+	PVRSRV_DC_BUFFER 					sSystemBuffer;
+	struct PVRSRV_DC_SWAPCHAIN_TAG		*psDCSwapChainShared;
+} PVRSRV_DISPLAYCLASS_INFO;
+
+
+typedef struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO_TAG
+{
+	PVRSRV_DISPLAYCLASS_INFO			*psDCInfo;
+	PRESMAN_ITEM						hResItem;
+} PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO;
+
+
+typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG *PPVRSRV_BC_SRV2BUFFER_KMJTABLE;
+
+typedef struct PVRSRV_BC_BUFFER_TAG
+{
+
+	PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
+
+	struct PVRSRV_BUFFERCLASS_INFO_TAG *psBCInfo;
+} PVRSRV_BC_BUFFER;
+
+
+typedef struct PVRSRV_BUFFERCLASS_INFO_TAG
+{
+	IMG_UINT32 							ui32RefCount;
+	IMG_UINT32							ui32DeviceID;
+	IMG_HANDLE							hExtDevice;
+	PPVRSRV_BC_SRV2BUFFER_KMJTABLE		psFuncTable;
+	IMG_HANDLE							hDevMemContext;
+
+	IMG_UINT32							ui32BufferCount;
+	PVRSRV_BC_BUFFER 					*psBuffer;
+
+} PVRSRV_BUFFERCLASS_INFO;
+
+
+typedef struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO_TAG
+{
+	PVRSRV_BUFFERCLASS_INFO				*psBCInfo;
+	IMG_HANDLE							hResItem;
+} PVRSRV_BUFFERCLASS_PERCONTEXT_INFO;
+
+
+static PVRSRV_DISPLAYCLASS_INFO* DCDeviceHandleToDCInfo (IMG_HANDLE hDeviceKM)
+{
+	PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+
+	psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+	return psDCPerContextInfo->psDCInfo;
+}
+
+
+static PVRSRV_BUFFERCLASS_INFO* BCDeviceHandleToBCInfo (IMG_HANDLE hDeviceKM)
+{
+	PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+
+	psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+	return psBCPerContextInfo->psBCInfo;
+}
+
+IMG_VOID PVRSRVEnumerateDCKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+	IMG_UINT *pui32DevCount;
+	IMG_UINT32 **ppui32DevID;
+	PVRSRV_DEVICE_CLASS peDeviceClass;
+
+	pui32DevCount = va_arg(va, IMG_UINT*);
+	ppui32DevID = va_arg(va, IMG_UINT32**);
+	peDeviceClass = va_arg(va, PVRSRV_DEVICE_CLASS);
+
+	if	((psDeviceNode->sDevId.eDeviceClass == peDeviceClass)
+	&&	(psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_EXT))
+	{
+		(*pui32DevCount)++;
+		if(*ppui32DevID)
+		{
+			*(*ppui32DevID)++ = psDeviceNode->sDevId.ui32DeviceIndex;
+		}
+	}
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumerateDCKM (PVRSRV_DEVICE_CLASS DeviceClass,
+								  IMG_UINT32 *pui32DevCount,
+								  IMG_UINT32 *pui32DevID )
+{
+
+	IMG_UINT			ui32DevCount = 0;
+	SYS_DATA 			*psSysData;
+	IMG_UINT32			pui32Temp[PVRSRV_MAX_DEVICES];
+	int					i;
+
+	SysAcquireData(&psSysData);
+
+
+	List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+										PVRSRVEnumerateDCKM_ForEachVaCb,
+										&ui32DevCount,
+										&pui32DevID,
+										DeviceClass);
+
+	if(pui32DevCount)
+	{
+		*pui32DevCount = ui32DevCount;
+	}
+	else if(pui32DevID == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDCKM: Invalid parameters"));
+		return (PVRSRV_ERROR_INVALID_PARAMS);
+	}
+
+
+
+	/* Note: The above macro returns the device IDs in the opposite order that
+	 * they were registered in, which messes up EMGD's DIH (dual independant
+	 * head) code.  To fix that, we need to reverse the order of the device
+	 * IDs:
+	 */
+	/* 1st) make a temporary copy of the array, in the correct order: */
+	for (i=0; i<ui32DevCount; i++) {
+		pui32Temp[i] = *(--pui32DevID);
+	}
+	/* 2nd) make a final version of the array, in the correct order: */
+	for (i=0; i<ui32DevCount; i++) {
+		pui32DevID[i] = pui32Temp[i];
+	}
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
+									   IMG_UINT32 *pui32DeviceID)
+{
+	PVRSRV_DISPLAYCLASS_INFO 	*psDCInfo = IMG_NULL;
+	PVRSRV_DEVICE_NODE			*psDeviceNode;
+	SYS_DATA					*psSysData;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	SysAcquireData(&psSysData);
+
+
+
+
+
+
+	if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof(*psDCInfo),
+					 (IMG_VOID **)&psDCInfo, IMG_NULL,
+					 "Display Class Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDCInfo alloc"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	OSMemSet (psDCInfo, 0, sizeof(*psDCInfo));
+
+
+	if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE),
+					 (IMG_VOID **)&psDCInfo->psFuncTable, IMG_NULL,
+					 "Function table for SRVKM->DISPLAY") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psFuncTable alloc"));
+		goto ErrorExit;
+	}
+	OSMemSet (psDCInfo->psFuncTable, 0, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE));
+
+
+	*psDCInfo->psFuncTable = *psFuncTable;
+
+
+	if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_DEVICE_NODE),
+					 (IMG_VOID **)&psDeviceNode, IMG_NULL,
+					 "Device Node") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDeviceNode alloc"));
+		goto ErrorExit;
+	}
+	OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+	psDeviceNode->pvDevice = (IMG_VOID*)psDCInfo;
+	psDeviceNode->ui32pvDeviceSize = sizeof(*psDCInfo);
+	psDeviceNode->ui32RefCount = 1;
+	psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
+	psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_DISPLAY;
+	psDeviceNode->psSysData = psSysData;
+
+
+	if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
+		goto ErrorExit;
+	}
+	psDCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+	if (pui32DeviceID)
+	{
+		*pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+	}
+
+
+	SysRegisterExternalDevice(psDeviceNode);
+
+
+	List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+	return PVRSRV_OK;
+
+ErrorExit:
+
+	if(psDCInfo->psFuncTable)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL);
+		psDCInfo->psFuncTable = IMG_NULL;
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
+
+
+	return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(IMG_UINT32 ui32DevIndex)
+{
+	SYS_DATA					*psSysData;
+	PVRSRV_DEVICE_NODE			*psDeviceNode;
+	PVRSRV_DISPLAYCLASS_INFO	*psDCInfo;
+
+	SysAcquireData(&psSysData);
+
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE*)
+		List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+									   MatchDeviceKM_AnyVaCb,
+									   ui32DevIndex,
+									   IMG_FALSE,
+									   PVRSRV_DEVICE_CLASS_DISPLAY);
+	if (!psDeviceNode)
+	{
+
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: requested device %d not present", ui32DevIndex));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+
+	psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
+
+
+
+
+	if(psDCInfo->ui32RefCount == 0)
+	{
+
+
+		List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
+
+
+		SysRemoveExternalDevice(psDeviceNode);
+
+
+
+
+		PVR_ASSERT(psDCInfo->ui32RefCount == 0);
+		(IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+		(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL);
+		psDCInfo->psFuncTable = IMG_NULL;
+		(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
+
+		(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: failed as %d Services DC API connections are still open", psDCInfo->ui32RefCount));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVRegisterBCDeviceKM (PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTable,
+									   IMG_UINT32	*pui32DeviceID)
+{
+	PVRSRV_BUFFERCLASS_INFO	*psBCInfo = IMG_NULL;
+	PVRSRV_DEVICE_NODE		*psDeviceNode;
+	SYS_DATA				*psSysData;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	SysAcquireData(&psSysData);
+
+
+
+
+
+	if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof(*psBCInfo),
+					 (IMG_VOID **)&psBCInfo, IMG_NULL,
+					 "Buffer Class Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psBCInfo alloc"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	OSMemSet (psBCInfo, 0, sizeof(*psBCInfo));
+
+
+	if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE),
+					 (IMG_VOID **)&psBCInfo->psFuncTable, IMG_NULL,
+					 "Function table for SRVKM->BUFFER") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psFuncTable alloc"));
+		goto ErrorExit;
+	}
+	OSMemSet (psBCInfo->psFuncTable, 0, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE));
+
+
+	*psBCInfo->psFuncTable = *psFuncTable;
+
+
+	if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_DEVICE_NODE),
+					 (IMG_VOID **)&psDeviceNode, IMG_NULL,
+					 "Device Node") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psDeviceNode alloc"));
+		goto ErrorExit;
+	}
+	OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+	psDeviceNode->pvDevice = (IMG_VOID*)psBCInfo;
+	psDeviceNode->ui32pvDeviceSize = sizeof(*psBCInfo);
+	psDeviceNode->ui32RefCount = 1;
+	psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
+	psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_BUFFER;
+	psDeviceNode->psSysData = psSysData;
+
+
+	if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
+		goto ErrorExit;
+	}
+	psBCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+	if (pui32DeviceID)
+	{
+		*pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+	}
+
+
+	List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+	return PVRSRV_OK;
+
+ErrorExit:
+
+	if(psBCInfo->psFuncTable)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PPVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL);
+		psBCInfo->psFuncTable = IMG_NULL;
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
+
+
+	return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+
+PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(IMG_UINT32 ui32DevIndex)
+{
+	SYS_DATA					*psSysData;
+	PVRSRV_DEVICE_NODE			*psDevNode;
+	PVRSRV_BUFFERCLASS_INFO		*psBCInfo;
+
+	SysAcquireData(&psSysData);
+
+
+	psDevNode = (PVRSRV_DEVICE_NODE*)
+		List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+									   MatchDeviceKM_AnyVaCb,
+									   ui32DevIndex,
+									   IMG_FALSE,
+									   PVRSRV_DEVICE_CLASS_BUFFER);
+
+	if (!psDevNode)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: requested device %d not present", ui32DevIndex));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+
+
+	psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDevNode->pvDevice;
+
+
+
+
+	if(psBCInfo->ui32RefCount == 0)
+	{
+
+
+		List_PVRSRV_DEVICE_NODE_Remove(psDevNode);
+
+
+
+
+		(IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+
+
+		(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL);
+		psBCInfo->psFuncTable = IMG_NULL;
+		(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
+
+		(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDevNode, IMG_NULL);
+
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: failed as %d Services BC API connections are still open", psBCInfo->ui32RefCount));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCloseDCDeviceKM (IMG_HANDLE	hDeviceKM,
+									IMG_BOOL	bResManCallback)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+
+	PVR_UNREFERENCED_PARAMETER(bResManCallback);
+
+	psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+
+	eError = ResManFreeResByPtr(psDCPerContextInfo->hResItem);
+
+	return eError;
+}
+
+
+static PVRSRV_ERROR CloseDCDeviceCallBack(IMG_PVOID		pvParam,
+										  IMG_UINT32	ui32Param)
+{
+	PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+	psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)pvParam;
+	psDCInfo = psDCPerContextInfo->psDCInfo;
+
+	psDCInfo->ui32RefCount--;
+	if(psDCInfo->ui32RefCount == 0)
+	{
+
+		psDCInfo->psFuncTable->pfnCloseDCDevice(psDCInfo->hExtDevice);
+
+		if (--psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+		{
+			PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
+		}
+
+		psDCInfo->hDevMemContext = IMG_NULL;
+		psDCInfo->hExtDevice = IMG_NULL;
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO), psDCPerContextInfo, IMG_NULL);
+
+
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA	*psPerProc,
+								   IMG_UINT32				ui32DeviceID,
+								   IMG_HANDLE				hDevCookie,
+								   IMG_HANDLE				*phDeviceKM)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+	PVRSRV_DEVICE_NODE	*psDeviceNode;
+	SYS_DATA			*psSysData;
+	PVRSRV_ERROR eError;
+
+	if(!phDeviceKM || !hDevCookie)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Invalid params"));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	SysAcquireData(&psSysData);
+
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE*)
+			List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+										   MatchDeviceKM_AnyVaCb,
+										   ui32DeviceID,
+										   IMG_FALSE,
+										   PVRSRV_DEVICE_CLASS_DISPLAY);
+	if (!psDeviceNode)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: no devnode matching index %d", ui32DeviceID));
+		return PVRSRV_ERROR_GENERIC;
+	}
+	psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
+
+
+
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(*psDCPerContextInfo),
+				  (IMG_VOID **)&psDCPerContextInfo, IMG_NULL,
+				  "Display Class per Context Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed psDCPerContextInfo alloc"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	OSMemSet(psDCPerContextInfo, 0, sizeof(*psDCPerContextInfo));
+
+	if(psDCInfo->ui32RefCount++ == 0)
+	{
+
+		psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+		psDCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+
+		eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+									(IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext,
+									&psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed sync info alloc"));
+			psDCInfo->ui32RefCount--;
+			return eError;
+		}
+
+
+		eError = psDCInfo->psFuncTable->pfnOpenDCDevice(ui32DeviceID,
+	&psDCInfo->hExtDevice,
+								(PVRSRV_SYNC_DATA*)psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to open external DC device"));
+			psDCInfo->ui32RefCount--;
+			PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
+			return eError;
+		}
+
+		psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
+	}
+
+	psDCPerContextInfo->psDCInfo = psDCInfo;
+	psDCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+													 RESMAN_TYPE_DISPLAYCLASS_DEVICE,
+													 psDCPerContextInfo,
+													 0,
+													 CloseDCDeviceCallBack);
+
+
+	*phDeviceKM = (IMG_HANDLE)psDCPerContextInfo;
+
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumDCFormatsKM (IMG_HANDLE hDeviceKM,
+									IMG_UINT32 *pui32Count,
+									DISPLAY_FORMAT *psFormat)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+	/* Note: It is acceptable for psFormat to be NULL.  In fact, this is the
+	 * desired way in which to find out the number of pixel formats, so that
+	 * memory can be allocated before a second call to this function, in order
+	 * to get the pixel formats.
+	 */
+	/*	if(!hDeviceKM || !pui32Count || !psFormat)*/
+	if(!hDeviceKM || !pui32Count)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCFormatsKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+	return psDCInfo->psFuncTable->pfnEnumDCFormats(psDCInfo->hExtDevice, pui32Count, psFormat);
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumDCDimsKM (IMG_HANDLE hDeviceKM,
+								 DISPLAY_FORMAT *psFormat,
+								 IMG_UINT32 *pui32Count,
+								 DISPLAY_DIMS *psDim)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+	if(!hDeviceKM || !pui32Count || !psFormat)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCDimsKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+	return psDCInfo->psFuncTable->pfnEnumDCDims(psDCInfo->hExtDevice, psFormat, pui32Count, psDim);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM,
+										IMG_HANDLE *phBuffer)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	IMG_HANDLE hExtBuffer;
+
+	if(!hDeviceKM || !phBuffer)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+	eError = psDCInfo->psFuncTable->pfnGetDCSystemBuffer(psDCInfo->hExtDevice, &hExtBuffer);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Failed to get valid buffer handle from external driver"));
+		return eError;
+	}
+
+
+	psDCInfo->sSystemBuffer.sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
+	psDCInfo->sSystemBuffer.sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
+	psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
+	psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer = hExtBuffer;
+
+	psDCInfo->sSystemBuffer.psDCInfo = psDCInfo;
+
+
+	*phBuffer = (IMG_HANDLE)&(psDCInfo->sSystemBuffer);
+
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCInfoKM (IMG_HANDLE hDeviceKM,
+								DISPLAY_INFO *psDisplayInfo)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_ERROR eError;
+
+	if(!hDeviceKM || !psDisplayInfo)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCInfoKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+	eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, psDisplayInfo);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	if (psDisplayInfo->ui32MaxSwapChainBuffers > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS)
+	{
+		psDisplayInfo->ui32MaxSwapChainBuffers = PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(IMG_HANDLE hSwapChainRef)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef;
+
+	if(!hSwapChainRef)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyDCSwapChainKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psSwapChainRef = hSwapChainRef;
+
+	eError = ResManFreeResByPtr(psSwapChainRef->hResItem);
+
+	return eError;
+}
+
+
+static PVRSRV_ERROR DestroyDCSwapChain(PVRSRV_DC_SWAPCHAIN *psSwapChain)
+{
+	PVRSRV_ERROR				eError;
+	PVRSRV_DISPLAYCLASS_INFO	*psDCInfo = psSwapChain->psDCInfo;
+	IMG_UINT32 i;
+	int timeout = 30;
+
+
+
+	if( psDCInfo->psDCSwapChainShared )
+	{
+		if( psDCInfo->psDCSwapChainShared == psSwapChain )
+		{
+			psDCInfo->psDCSwapChainShared = psSwapChain->psNext;
+		}
+		else
+		{
+			PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain;
+			psCurrentSwapChain = psDCInfo->psDCSwapChainShared;
+			while( psCurrentSwapChain->psNext )
+			{
+				if( psCurrentSwapChain->psNext != psSwapChain )
+				{
+					psCurrentSwapChain = psCurrentSwapChain->psNext;
+					continue;
+				}
+				psCurrentSwapChain->psNext = psSwapChain->psNext;
+				break;
+			}
+		}
+	}
+
+	if (psSwapChain->psQueue)
+	{
+		do
+		{
+			eError = PVRSRVDestroyCommandQueueKM(psSwapChain->psQueue);
+		} while (eError != PVRSRV_OK && (timeout-- > 0));
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"DestroyDCSwapChainCallBack: Failed to destroy command queue"));
+		}
+	}
+
+	eError = psDCInfo->psFuncTable->pfnDestroyDCSwapChain(psDCInfo->hExtDevice,
+															psSwapChain->hExtSwapChain);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DestroyDCSwapChainCallBack: Failed to destroy DC swap chain"));
+		return eError;
+	}
+
+
+	for(i=0; i<psSwapChain->ui32BufferCount; i++)
+	{
+		if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+		{
+			if (--psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+			{
+				PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+			}
+		}
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
+
+
+	return eError;
+}
+
+
+static PVRSRV_ERROR DestroyDCSwapChainRefCallBack(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+	PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF *) pvParam;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+	if(--psSwapChainRef->psSwapChain->ui32RefCount == 0)
+	{
+		eError = DestroyDCSwapChain(psSwapChainRef->psSwapChain);
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN_REF), psSwapChainRef, IMG_NULL);
+	return eError;
+}
+
+static PVRSRV_DC_SWAPCHAIN* PVRSRVFindSharedDCSwapChainKM(PVRSRV_DISPLAYCLASS_INFO *psDCInfo,
+														 IMG_UINT32 ui32SwapChainID)
+{
+	PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain;
+
+	for(psCurrentSwapChain = psDCInfo->psDCSwapChainShared;
+		psCurrentSwapChain;
+		psCurrentSwapChain = psCurrentSwapChain->psNext)
+	{
+		if(psCurrentSwapChain->ui32SwapChainID == ui32SwapChainID)
+			return psCurrentSwapChain;
+	}
+	return IMG_NULL;
+}
+
+static PVRSRV_ERROR PVRSRVCreateDCSwapChainRefKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+												 PVRSRV_DC_SWAPCHAIN 		*psSwapChain,
+												 PVRSRV_DC_SWAPCHAIN_REF 	**ppsSwapChainRef)
+{
+	PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL;
+
+
+	if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_DC_SWAPCHAIN_REF),
+					 (IMG_VOID **)&psSwapChainRef, IMG_NULL,
+					 "Display Class Swapchain Reference") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainRefKM: Failed psSwapChainRef alloc"));
+		return  PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	OSMemSet (psSwapChainRef, 0, sizeof(PVRSRV_DC_SWAPCHAIN_REF));
+
+
+	psSwapChain->ui32RefCount++;
+
+
+	psSwapChainRef->psSwapChain = psSwapChain;
+	psSwapChainRef->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+												  RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
+												  psSwapChainRef,
+												  0,
+												  &DestroyDCSwapChainRefCallBack);
+	*ppsSwapChainRef = psSwapChainRef;
+
+	return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA	*psPerProc,
+										IMG_HANDLE				hDeviceKM,
+										IMG_UINT32				ui32Flags,
+										DISPLAY_SURF_ATTRIBUTES	*psDstSurfAttrib,
+										DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+										IMG_UINT32				ui32BufferCount,
+										IMG_UINT32				ui32OEMFlags,
+										IMG_HANDLE				*phSwapChainRef,
+										IMG_UINT32				*pui32SwapChainID)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_SWAPCHAIN *psSwapChain = IMG_NULL;
+	PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL;
+	PVRSRV_SYNC_DATA *apsSyncData[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+	PVRSRV_QUEUE_INFO *psQueue = IMG_NULL;
+	PVRSRV_ERROR eError;
+	IMG_UINT32 i;
+	DISPLAY_INFO sDisplayInfo;
+	int timeout = 30;
+
+
+	if(!hDeviceKM
+	|| !psDstSurfAttrib
+	|| !psSrcSurfAttrib
+	|| !phSwapChainRef
+	|| !pui32SwapChainID)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if (ui32BufferCount > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too many buffers"));
+		return PVRSRV_ERROR_TOOMANYBUFFERS;
+	}
+
+#if 0 /* Removing limiation  to allow 1 buffer allocations */
+	if (ui32BufferCount < 2)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too few buffers"));
+		return PVRSRV_ERROR_TOO_FEW_BUFFERS;
+	}
+#endif
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+	if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_QUERY )
+	{
+
+		psSwapChain = PVRSRVFindSharedDCSwapChainKM(psDCInfo, *pui32SwapChainID );
+		if( psSwapChain  )
+		{
+			PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVCreateDCSwapChainKM: found query"));
+
+			eError = PVRSRVCreateDCSwapChainRefKM(psPerProc,
+												  psSwapChain,
+												  &psSwapChainRef);
+			if( eError != PVRSRV_OK )
+			{
+				PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference"));
+				return eError;
+			}
+
+			*phSwapChainRef = (IMG_HANDLE)psSwapChainRef;
+			return PVRSRV_OK;
+		}
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: No shared SwapChain found for query"));
+		return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
+	}
+
+
+	if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_DC_SWAPCHAIN),
+					 (IMG_VOID **)&psSwapChain, IMG_NULL,
+					 "Display Class Swapchain") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed psSwapChain alloc"));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto ErrorExit;
+	}
+
+	OSMemSet (psSwapChain, 0, sizeof(PVRSRV_DC_SWAPCHAIN));
+
+	if (ui32OEMFlags & (PVR2D_CREATE_FLIPCHAIN_OEMDISPLAY |
+				PVR2D_CREATE_FLIPCHAIN_OEMGENERAL |
+				PVR2D_CREATE_FLIPCHAIN_OEMOVERLAY))
+	{
+		psQueue = NULL;
+	}
+	else
+	{
+		do
+		{
+			eError = PVRSRVCreateCommandQueueKM(1024, &psQueue);
+		} while (eError != PVRSRV_OK && (timeout-- > 0));
+
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create CmdQueue"));
+			goto ErrorExit;
+		}
+	}
+
+	psSwapChain->psQueue = psQueue;
+
+	for(i=0; i<ui32BufferCount; i++)
+	{
+		eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+										psDCInfo->hDevMemContext,
+										&psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to alloc syninfo for psSwapChain"));
+			goto ErrorExit;
+		}
+
+		psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
+
+
+		psSwapChain->asBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
+		psSwapChain->asBuffer[i].sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
+		psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
+
+
+		psSwapChain->asBuffer[i].psDCInfo = psDCInfo;
+		psSwapChain->asBuffer[i].psSwapChain = psSwapChain;
+
+
+		apsSyncData[i] = (PVRSRV_SYNC_DATA*)psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
+	}
+
+	psSwapChain->ui32BufferCount = ui32BufferCount;
+	psSwapChain->psDCInfo = psDCInfo;
+
+	eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, &sDisplayInfo);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to get DC info"));
+		return eError;
+	}
+
+
+	eError =  psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice,
+														ui32Flags,
+														psDstSurfAttrib,
+														psSrcSurfAttrib,
+														ui32BufferCount,
+														apsSyncData,
+														ui32OEMFlags,
+														&psSwapChain->hExtSwapChain,
+														&psSwapChain->ui32SwapChainID);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create 3rd party SwapChain"));
+		goto ErrorExit;
+	}
+
+
+	eError = PVRSRVCreateDCSwapChainRefKM(psPerProc,
+										  psSwapChain,
+										  &psSwapChainRef);
+	if( eError != PVRSRV_OK )
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference"));
+		goto ErrorExit;
+	}
+
+	psSwapChain->ui32RefCount = 1;
+	psSwapChain->ui32Flags = ui32Flags;
+
+
+	if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_SHARED )
+	{
+		if(! psDCInfo->psDCSwapChainShared )
+		{
+			psDCInfo->psDCSwapChainShared = psSwapChain;
+		}
+		else
+		{
+			PVRSRV_DC_SWAPCHAIN *psOldHead = psDCInfo->psDCSwapChainShared;
+			psDCInfo->psDCSwapChainShared = psSwapChain;
+			psSwapChain->psNext = psOldHead;
+		}
+	}
+
+
+	*pui32SwapChainID = psSwapChain->ui32SwapChainID;
+
+
+	*phSwapChainRef= (IMG_HANDLE)psSwapChainRef;
+
+	return eError;
+
+ErrorExit:
+
+	for(i=0; i<ui32BufferCount; i++)
+	{
+		if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+		{
+			if (--psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+			{
+				PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+			}
+		}
+	}
+
+	if(psQueue)
+	{
+		PVRSRVDestroyCommandQueueKM(psQueue);
+	}
+
+	if(psSwapChain)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
+
+	}
+
+	return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCDstRectKM(IMG_HANDLE	hDeviceKM,
+								  IMG_HANDLE	hSwapChainRef,
+								  IMG_RECT		*psRect)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+	if(!hDeviceKM || !hSwapChainRef)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstRectKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+	psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+	return psDCInfo->psFuncTable->pfnSetDCDstRect(psDCInfo->hExtDevice,
+													psSwapChain->hExtSwapChain,
+													psRect);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCSrcRectKM(IMG_HANDLE	hDeviceKM,
+								  IMG_HANDLE	hSwapChainRef,
+								  IMG_RECT		*psRect)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+	if(!hDeviceKM || !hSwapChainRef)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcRectKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+	psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+	return psDCInfo->psFuncTable->pfnSetDCSrcRect(psDCInfo->hExtDevice,
+													psSwapChain->hExtSwapChain,
+													psRect);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(IMG_HANDLE	hDeviceKM,
+									   IMG_HANDLE	hSwapChainRef,
+									   IMG_UINT32	ui32CKColour)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+	if(!hDeviceKM || !hSwapChainRef)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstColourKeyKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+	psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+	return psDCInfo->psFuncTable->pfnSetDCDstColourKey(psDCInfo->hExtDevice,
+														psSwapChain->hExtSwapChain,
+														ui32CKColour);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(IMG_HANDLE	hDeviceKM,
+									   IMG_HANDLE	hSwapChainRef,
+									   IMG_UINT32	ui32CKColour)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+	if(!hDeviceKM || !hSwapChainRef)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcColourKeyKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+	psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+	return psDCInfo->psFuncTable->pfnSetDCSrcColourKey(psDCInfo->hExtDevice,
+														psSwapChain->hExtSwapChain,
+														ui32CKColour);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE	hDeviceKM,
+								  IMG_HANDLE	hSwapChainRef,
+								  IMG_UINT32	*pui32BufferCount,
+								  IMG_HANDLE	*phBuffer)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_SWAPCHAIN *psSwapChain;
+	IMG_HANDLE ahExtBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+	PVRSRV_ERROR eError;
+	IMG_UINT32 i;
+
+	if(!hDeviceKM || !hSwapChainRef || !phBuffer)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCBuffersKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+	psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+
+	eError = psDCInfo->psFuncTable->pfnGetDCBuffers(psDCInfo->hExtDevice,
+													psSwapChain->hExtSwapChain,
+													pui32BufferCount,
+													ahExtBuffer);
+
+	PVR_ASSERT(*pui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+
+
+
+	for(i=0; i<*pui32BufferCount; i++)
+	{
+		psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtBuffer = ahExtBuffer[i];
+		phBuffer[i] = (IMG_HANDLE)&psSwapChain->asBuffer[i];
+	}
+
+	return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE	hDeviceKM,
+									IMG_HANDLE	hBuffer,
+									IMG_UINT32	ui32SwapInterval,
+									IMG_HANDLE	hPrivateTag,
+									IMG_UINT32	ui32ClipRectCount,
+									IMG_RECT	*psClipRect)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_BUFFER *psBuffer;
+	PVRSRV_QUEUE_INFO *psQueue;
+	DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+	IMG_UINT32 i;
+	IMG_BOOL bAddReferenceToLast = IMG_TRUE;
+	IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND;
+	IMG_UINT32 ui32NumSrcSyncs = 1;
+	PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+	PVRSRV_COMMAND *psCommand;
+
+	if(!hDeviceKM || !hBuffer || !psClipRect)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+#if defined(SUPPORT_LMA)
+	eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+	if(eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+#endif
+
+	psBuffer = (PVRSRV_DC_BUFFER*)hBuffer;
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+
+	if(psDCInfo->psFuncTable->pfnQuerySwapCommandID != IMG_NULL)
+	{
+		psDCInfo->psFuncTable->pfnQuerySwapCommandID(psDCInfo->hExtDevice,
+													 psBuffer->psSwapChain->hExtSwapChain,
+													 psBuffer->sDeviceClassBuffer.hExtBuffer,
+													 hPrivateTag,
+													 &ui16SwapCommandID,
+													 &bAddReferenceToLast);
+
+	}
+
+#endif
+
+	psQueue = psBuffer->psSwapChain->psQueue;
+
+	if (!psQueue)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Non-flippable swap chain"));
+		goto Exit;
+	}
+
+	apsSrcSync[0] = psBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+
+
+
+	if(bAddReferenceToLast && psBuffer->psSwapChain->psLastFlipBuffer &&
+		psBuffer != psBuffer->psSwapChain->psLastFlipBuffer)
+	{
+		apsSrcSync[1] = psBuffer->psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+
+
+
+		ui32NumSrcSyncs++;
+	}
+
+
+	eError = PVRSRVInsertCommandKM (psQueue,
+									&psCommand,
+									psDCInfo->ui32DeviceID,
+									ui16SwapCommandID,
+									0,
+									IMG_NULL,
+									ui32NumSrcSyncs,
+									apsSrcSync,
+									sizeof(DISPLAYCLASS_FLIP_COMMAND) + (sizeof(IMG_RECT) * ui32ClipRectCount));
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to get space in queue"));
+		goto Exit;
+	}
+
+
+	psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
+
+
+	psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+
+	psFlipCmd->hExtSwapChain = psBuffer->psSwapChain->hExtSwapChain;
+
+
+	psFlipCmd->hExtBuffer = psBuffer->sDeviceClassBuffer.hExtBuffer;
+
+
+	psFlipCmd->hPrivateTag = hPrivateTag;
+
+
+	psFlipCmd->ui32ClipRectCount = ui32ClipRectCount;
+
+	psFlipCmd->psClipRect = (IMG_RECT*)((IMG_UINT8*)psFlipCmd + sizeof(DISPLAYCLASS_FLIP_COMMAND));
+
+	for(i=0; i<ui32ClipRectCount; i++)
+	{
+		psFlipCmd->psClipRect[i] = psClipRect[i];
+	}
+
+
+	psFlipCmd->ui32SwapInterval = ui32SwapInterval;
+
+
+	eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to submit command"));
+		goto Exit;
+	}
+
+
+
+
+
+
+
+
+
+
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		if(PVRSRVProcessQueues(KERNEL_ID, IMG_FALSE) != PVRSRV_ERROR_PROCESSING_BLOCKED)
+		{
+			goto ProcessedQueues;
+		}
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to process queues"));
+
+	eError = PVRSRV_ERROR_GENERIC;
+	goto Exit;
+
+ProcessedQueues:
+
+	psBuffer->psSwapChain->psLastFlipBuffer = psBuffer;
+
+Exit:
+
+	if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+	{
+		eError = PVRSRV_ERROR_RETRY;
+	}
+
+#if defined(SUPPORT_LMA)
+	PVRSRVPowerUnlock(KERNEL_ID);
+#endif
+	return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE	hDeviceKM,
+									IMG_HANDLE	hSwapChainRef)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_QUEUE_INFO *psQueue;
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_SWAPCHAIN *psSwapChain;
+	PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef;
+	DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+	IMG_UINT32 ui32NumSrcSyncs = 1;
+	PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+	PVRSRV_COMMAND *psCommand;
+	IMG_BOOL bAddReferenceToLast = IMG_TRUE;
+	IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND;
+
+	if(!hDeviceKM || !hSwapChainRef)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+#if defined(SUPPORT_LMA)
+	eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+	if(eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+#endif
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+	psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef;
+	psSwapChain = psSwapChainRef->psSwapChain;
+
+
+	psQueue = psSwapChain->psQueue;
+
+	if (!psQueue)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Non-flippable swap chain"));
+		goto Exit;
+	}
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+
+	if(psDCInfo->psFuncTable->pfnQuerySwapCommandID != IMG_NULL)
+	{
+		psDCInfo->psFuncTable->pfnQuerySwapCommandID(psDCInfo->hExtDevice,
+													 psSwapChain->hExtSwapChain,
+													 psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer,
+													 0,
+													 &ui16SwapCommandID,
+													 &bAddReferenceToLast);
+
+	}
+
+#endif
+
+
+	apsSrcSync[0] = psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo;
+
+
+
+	if(bAddReferenceToLast && psSwapChain->psLastFlipBuffer)
+	{
+
+		if (apsSrcSync[0] != psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo)
+		{
+			apsSrcSync[1] = psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+
+
+
+			ui32NumSrcSyncs++;
+		}
+	}
+
+
+	eError = PVRSRVInsertCommandKM (psQueue,
+									&psCommand,
+									psDCInfo->ui32DeviceID,
+									ui16SwapCommandID,
+									0,
+									IMG_NULL,
+									ui32NumSrcSyncs,
+									apsSrcSync,
+									sizeof(DISPLAYCLASS_FLIP_COMMAND));
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to get space in queue"));
+		goto Exit;
+	}
+
+
+	psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
+
+
+	psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+
+	psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain;
+
+
+	psFlipCmd->hExtBuffer = psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer;
+
+
+	psFlipCmd->hPrivateTag = IMG_NULL;
+
+
+	psFlipCmd->ui32ClipRectCount = 0;
+
+	psFlipCmd->ui32SwapInterval = 1;
+
+
+	eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to submit command"));
+		goto Exit;
+	}
+
+
+
+
+
+
+
+
+
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		if(PVRSRVProcessQueues(KERNEL_ID, IMG_FALSE) != PVRSRV_ERROR_PROCESSING_BLOCKED)
+		{
+			goto ProcessedQueues;
+		}
+
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to process queues"));
+	eError = PVRSRV_ERROR_GENERIC;
+	goto Exit;
+
+ProcessedQueues:
+
+	psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer;
+
+	eError = PVRSRV_OK;
+
+Exit:
+
+	if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+	{
+		eError = PVRSRV_ERROR_RETRY;
+	}
+
+#if defined(SUPPORT_LMA)
+	PVRSRVPowerUnlock(KERNEL_ID);
+#endif
+	return eError;
+}
+
+
+PVRSRV_ERROR PVRSRVRegisterSystemISRHandler (PFN_ISR_HANDLER	pfnISRHandler,
+											 IMG_VOID			*pvISRHandlerData,
+											 IMG_UINT32			ui32ISRSourceMask,
+											 IMG_UINT32			ui32DeviceID)
+{
+	SYS_DATA 			*psSysData;
+	PVRSRV_DEVICE_NODE	*psDevNode;
+
+	PVR_UNREFERENCED_PARAMETER(ui32ISRSourceMask);
+
+	SysAcquireData(&psSysData);
+
+
+	psDevNode = (PVRSRV_DEVICE_NODE*)
+				List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+												MatchDeviceKM_AnyVaCb,
+												ui32DeviceID,
+												IMG_TRUE);
+
+	if (psDevNode == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterSystemISRHandler: Failed to get psDevNode"));
+		PVR_DBG_BREAK;
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+
+	psDevNode->pvISRData = (IMG_VOID*) pvISRHandlerData;
+
+
+	psDevNode->pfnDeviceISR	= pfnISRHandler;
+
+	return PVRSRV_OK;
+}
+
+IMG_VOID PVRSRVSetDCState_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	IMG_UINT32 ui32State;
+	ui32State = va_arg(va, IMG_UINT32);
+
+	if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY)
+	{
+		psDCInfo = (PVRSRV_DISPLAYCLASS_INFO *)psDeviceNode->pvDevice;
+		if (psDCInfo->psFuncTable->pfnSetDCState && psDCInfo->hExtDevice)
+		{
+			psDCInfo->psFuncTable->pfnSetDCState(psDCInfo->hExtDevice, ui32State);
+		}
+	}
+}
+
+
+IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State)
+{
+	SYS_DATA					*psSysData;
+
+	SysAcquireData(&psSysData);
+
+	List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+										PVRSRVSetDCState_ForEachVaCb,
+										ui32State);
+}
+
+
+IMG_EXPORT
+IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable)
+{
+	psJTable->ui32TableSize = sizeof(PVRSRV_DC_DISP2SRV_KMJTABLE);
+	psJTable->pfnPVRSRVRegisterDCDevice = PVRSRVRegisterDCDeviceKM;
+	psJTable->pfnPVRSRVRemoveDCDevice = PVRSRVRemoveDCDeviceKM;
+	psJTable->pfnPVRSRVOEMFunction = SysOEMFunction;
+	psJTable->pfnPVRSRVRegisterCmdProcList = PVRSRVRegisterCmdProcListKM;
+	psJTable->pfnPVRSRVRemoveCmdProcList = PVRSRVRemoveCmdProcListKM;
+#if defined(SUPPORT_MISR_IN_THREAD)
+        psJTable->pfnPVRSRVCmdComplete = OSVSyncMISR;
+#else
+        psJTable->pfnPVRSRVCmdComplete = PVRSRVCommandCompleteKM;
+#endif
+	psJTable->pfnPVRSRVRegisterSystemISRHandler = PVRSRVRegisterSystemISRHandler;
+	psJTable->pfnPVRSRVRegisterPowerDevice = PVRSRVRegisterPowerDevice;
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+	psJTable->pfnPVRSRVFreeCmdCompletePacket = &PVRSRVFreeCommandCompletePacketKM;
+#endif
+
+	return IMG_TRUE;
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCloseBCDeviceKM (IMG_HANDLE	hDeviceKM,
+									IMG_BOOL	bResManCallback)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+
+	PVR_UNREFERENCED_PARAMETER(bResManCallback);
+
+	psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+
+	eError = ResManFreeResByPtr(psBCPerContextInfo->hResItem);
+
+	return eError;
+}
+
+
+static PVRSRV_ERROR CloseBCDeviceCallBack(IMG_PVOID		pvParam,
+										  IMG_UINT32	ui32Param)
+{
+	PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+	PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+	psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)pvParam;
+	psBCInfo = psBCPerContextInfo->psBCInfo;
+
+	psBCInfo->ui32RefCount--;
+	if(psBCInfo->ui32RefCount == 0)
+	{
+		IMG_UINT32 i;
+
+
+		psBCInfo->psFuncTable->pfnCloseBCDevice(psBCInfo->ui32DeviceID, psBCInfo->hExtDevice);
+
+
+		for(i=0; i<psBCInfo->ui32BufferCount; i++)
+		{
+			if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+			{
+				if (--psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+				{
+					PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+				}
+			}
+		}
+
+
+		if(psBCInfo->psBuffer)
+		{
+			OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER), psBCInfo->psBuffer, IMG_NULL);
+			psBCInfo->psBuffer = IMG_NULL;
+		}
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_PERCONTEXT_INFO), psBCPerContextInfo, IMG_NULL);
+
+
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA	*psPerProc,
+								   IMG_UINT32				ui32DeviceID,
+								   IMG_HANDLE				hDevCookie,
+								   IMG_HANDLE				*phDeviceKM)
+{
+	PVRSRV_BUFFERCLASS_INFO	*psBCInfo;
+	PVRSRV_BUFFERCLASS_PERCONTEXT_INFO	*psBCPerContextInfo;
+	PVRSRV_DEVICE_NODE		*psDeviceNode;
+	SYS_DATA 				*psSysData;
+	IMG_UINT32 				i;
+	PVRSRV_ERROR			eError;
+
+	if(!phDeviceKM || !hDevCookie)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Invalid params"));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	SysAcquireData(&psSysData);
+
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE*)
+			List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+										   MatchDeviceKM_AnyVaCb,
+										   ui32DeviceID,
+										   IMG_FALSE,
+										   PVRSRV_DEVICE_CLASS_BUFFER);
+	if (!psDeviceNode)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: No devnode matching index %d", ui32DeviceID));
+		return PVRSRV_ERROR_GENERIC;
+	}
+	psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDeviceNode->pvDevice;
+
+
+
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(*psBCPerContextInfo),
+				  (IMG_VOID **)&psBCPerContextInfo, IMG_NULL,
+				  "Buffer Class per Context Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed psBCPerContextInfo alloc"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo));
+
+	if(psBCInfo->ui32RefCount++ == 0)
+	{
+		BUFFER_INFO sBufferInfo;
+
+		psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+		psBCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+
+		eError = psBCInfo->psFuncTable->pfnOpenBCDevice(ui32DeviceID, &psBCInfo->hExtDevice);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to open external BC device"));
+			return eError;
+		}
+
+
+		eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, &sBufferInfo);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM : Failed to get BC Info"));
+			return eError;
+		}
+
+
+		psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount;
+
+
+
+		eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+							  sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount,
+							  (IMG_VOID **)&psBCInfo->psBuffer,
+						 	  IMG_NULL,
+							  "Array of Buffer Class Buffer");
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to allocate BC buffers"));
+			return eError;
+		}
+		OSMemSet (psBCInfo->psBuffer,
+					0,
+					sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount);
+
+		for(i=0; i<psBCInfo->ui32BufferCount; i++)
+		{
+
+			eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+										psBCInfo->hDevMemContext,
+										&psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+			if(eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed sync info alloc"));
+				goto ErrorExit;
+			}
+
+			psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
+
+
+
+
+			eError = psBCInfo->psFuncTable->pfnGetBCBuffer(psBCInfo->hExtDevice,
+															i,
+															psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncData,
+															&psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtBuffer);
+			if(eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to get BC buffers"));
+				goto ErrorExit;
+			}
+
+
+			psBCInfo->psBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psBCInfo->psFuncTable->pfnGetBufferAddr;
+			psBCInfo->psBuffer[i].sDeviceClassBuffer.hDevMemContext = psBCInfo->hDevMemContext;
+			psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice = psBCInfo->hExtDevice;
+		}
+	}
+
+	psBCPerContextInfo->psBCInfo = psBCInfo;
+	psBCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+													 RESMAN_TYPE_BUFFERCLASS_DEVICE,
+													 psBCPerContextInfo,
+													 0,
+													 CloseBCDeviceCallBack);
+
+
+	*phDeviceKM = (IMG_HANDLE)psBCPerContextInfo;
+
+	return PVRSRV_OK;
+
+ErrorExit:
+
+
+	for(i=0; i<psBCInfo->ui32BufferCount; i++)
+	{
+		if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+		{
+			if (--psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+			{
+				PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+			}
+		}
+	}
+
+
+	if(psBCInfo->psBuffer)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER), psBCInfo->psBuffer, IMG_NULL);
+		psBCInfo->psBuffer = IMG_NULL;
+	}
+
+	return eError;
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetBCInfoKM (IMG_HANDLE hDeviceKM,
+								BUFFER_INFO *psBufferInfo)
+{
+	PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+	PVRSRV_ERROR 			eError;
+
+	if(!hDeviceKM || !psBufferInfo)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
+
+	eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, psBufferInfo);
+
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM : Failed to get BC Info"));
+		return eError;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetBCBufferKM (IMG_HANDLE hDeviceKM,
+								  IMG_UINT32 ui32BufferIndex,
+								  IMG_HANDLE *phBuffer)
+{
+	PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+	if(!hDeviceKM || !phBuffer)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
+
+	if(ui32BufferIndex < psBCInfo->ui32BufferCount)
+	{
+		*phBuffer = (IMG_HANDLE)&psBCInfo->psBuffer[ui32BufferIndex];
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Buffer index %d out of range (%d)", ui32BufferIndex,psBCInfo->ui32BufferCount));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetBCBufferIdFromTagKM(IMG_HANDLE hDeviceKM,
+								  IMG_UINT32 ui32BufferIndex,
+								  IMG_HANDLE pidx)
+{
+	PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+	PVRSRV_ERROR 			eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+	if(NULL == hDeviceKM)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: Invalid parameters", __FUNCTION__));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
+
+	if (NULL != psBCInfo->psFuncTable->pfnGetBufferIdFromTag) {
+		eError = psBCInfo->psFuncTable->pfnGetBufferIdFromTag(psBCInfo->hExtDevice,
+				ui32BufferIndex,
+				pidx);
+		if(eError != PVRSRV_OK) {
+			PVR_DPF((PVR_DBG_ERROR,"%s : Failed to get BC Buffer Index", __FUNCTION__));
+			return PVRSRV_ERROR_GENERIC;
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable)
+{
+	psJTable->ui32TableSize = sizeof(PVRSRV_BC_BUFFER2SRV_KMJTABLE);
+
+	psJTable->pfnPVRSRVRegisterBCDevice = PVRSRVRegisterBCDeviceKM;
+	psJTable->pfnPVRSRVRemoveBCDevice = PVRSRVRemoveBCDeviceKM;
+
+	return IMG_TRUE;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/devicemem.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/devicemem.c
new file mode 100644
index 0000000..1cf0c3c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/devicemem.c
@@ -0,0 +1,1546 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "pdump_km.h"
+#include "pvr_bridge_km.h"
+#include "mm.h"
+
+static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE		hDevCookie,
+									IMG_HANDLE		hDevMemHeap,
+									IMG_UINT32		ui32Flags,
+									IMG_SIZE_T		ui32Size,
+									IMG_SIZE_T		ui32Alignment,
+									PVRSRV_KERNEL_MEM_INFO	**ppsMemInfo);
+
+typedef struct _RESMAN_MAP_DEVICE_MEM_DATA_
+{
+
+	PVRSRV_KERNEL_MEM_INFO	*psMemInfo;
+
+	PVRSRV_KERNEL_MEM_INFO	*psSrcMemInfo;
+} RESMAN_MAP_DEVICE_MEM_DATA;
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie,
+													PVRSRV_HEAP_INFO *psHeapInfo)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	IMG_UINT32 ui32HeapCount;
+	DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+	IMG_UINT32 i;
+
+	if (hDevCookie == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetDeviceMemHeapsKM: hDevCookie invalid"));
+		PVR_DBG_BREAK;
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+	ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+	psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+
+	PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+
+	for(i=0; i<ui32HeapCount; i++)
+	{
+
+		psHeapInfo[i].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+		psHeapInfo[i].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+		psHeapInfo[i].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+		psHeapInfo[i].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+		psHeapInfo[i].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+	}
+
+	for(; i < PVRSRV_MAX_CLIENT_HEAPS; i++)
+	{
+		OSMemSet(psHeapInfo + i, 0, sizeof(*psHeapInfo));
+		psHeapInfo[i].ui32HeapID = (IMG_UINT32)PVRSRV_UNDEFINED_HEAP_ID;
+	}
+
+	return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE					hDevCookie,
+														 PVRSRV_PER_PROCESS_DATA	*psPerProc,
+														 IMG_HANDLE 				*phDevMemContext,
+														 IMG_UINT32 				*pui32ClientHeapCount,
+														 PVRSRV_HEAP_INFO			*psHeapInfo,
+														 IMG_BOOL					*pbCreated,
+														 IMG_BOOL 					*pbShared)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	IMG_UINT32 ui32HeapCount, ui32ClientHeapCount=0;
+	DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+	IMG_HANDLE hDevMemContext;
+	IMG_HANDLE hDevMemHeap;
+	IMG_DEV_PHYADDR sPDDevPAddr;
+	IMG_UINT32 i;
+
+#if !defined(PVR_SECURE_HANDLES)
+	PVR_UNREFERENCED_PARAMETER(pbShared);
+#endif
+
+	if (hDevCookie == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVCreateDeviceMemContextKM: hDevCookie invalid"));
+		PVR_DBG_BREAK;
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+
+	ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+	psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+
+
+	PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+
+
+	hDevMemContext = BM_CreateContext(psDeviceNode,
+									  &sPDDevPAddr,
+									  psPerProc,
+									  pbCreated);
+	if (hDevMemContext == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDeviceMemContextKM: Failed BM_CreateContext"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+
+	for(i=0; i<ui32HeapCount; i++)
+	{
+		switch(psDeviceMemoryHeap[i].DevMemHeapType)
+		{
+			case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+			{
+
+				psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+				psHeapInfo[ui32ClientHeapCount].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+				psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+				psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+				psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+				pbShared[ui32ClientHeapCount] = IMG_TRUE;
+#endif
+				ui32ClientHeapCount++;
+				break;
+			}
+			case DEVICE_MEMORY_HEAP_PERCONTEXT:
+			{
+				hDevMemHeap = BM_CreateHeap(hDevMemContext,
+											&psDeviceMemoryHeap[i]);
+
+
+				psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+				psHeapInfo[ui32ClientHeapCount].hDevMemHeap = hDevMemHeap;
+				psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+				psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+				psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+				pbShared[ui32ClientHeapCount] = IMG_FALSE;
+#endif
+
+				ui32ClientHeapCount++;
+				break;
+			}
+		}
+	}
+
+
+	*pui32ClientHeapCount = ui32ClientHeapCount;
+	*phDevMemContext = hDevMemContext;
+
+	return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContextKM(IMG_HANDLE hDevCookie,
+														  IMG_HANDLE hDevMemContext,
+														  IMG_BOOL *pbDestroyed)
+{
+	PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+	return BM_DestroyContext(hDevMemContext, pbDestroyed);
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE					hDevCookie,
+														 IMG_HANDLE 				hDevMemContext,
+														 IMG_UINT32 				*pui32ClientHeapCount,
+														 PVRSRV_HEAP_INFO			*psHeapInfo,
+														 IMG_BOOL 					*pbShared)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	IMG_UINT32 ui32HeapCount, ui32ClientHeapCount=0;
+	DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+	IMG_HANDLE hDevMemHeap;
+	IMG_UINT32 i;
+
+#if !defined(PVR_SECURE_HANDLES)
+	PVR_UNREFERENCED_PARAMETER(pbShared);
+#endif
+
+	if (hDevCookie == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetDeviceMemHeapInfoKM: hDevCookie invalid"));
+		PVR_DBG_BREAK;
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+
+	ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+	psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+
+
+	PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+
+	for(i=0; i<ui32HeapCount; i++)
+	{
+		switch(psDeviceMemoryHeap[i].DevMemHeapType)
+		{
+			case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+			{
+
+				psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+				psHeapInfo[ui32ClientHeapCount].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+				psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+				psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+				psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+				pbShared[ui32ClientHeapCount] = IMG_TRUE;
+#endif
+				ui32ClientHeapCount++;
+				break;
+			}
+			case DEVICE_MEMORY_HEAP_PERCONTEXT:
+			{
+				hDevMemHeap = BM_CreateHeap(hDevMemContext,
+											&psDeviceMemoryHeap[i]);
+
+
+				psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+				psHeapInfo[ui32ClientHeapCount].hDevMemHeap = hDevMemHeap;
+				psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+				psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+				psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+				pbShared[ui32ClientHeapCount] = IMG_FALSE;
+#endif
+
+				ui32ClientHeapCount++;
+				break;
+			}
+		}
+	}
+
+
+	*pui32ClientHeapCount = ui32ClientHeapCount;
+
+	return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE		hDevCookie,
+									IMG_HANDLE		hDevMemHeap,
+									IMG_UINT32		ui32Flags,
+									IMG_SIZE_T		ui32Size,
+									IMG_SIZE_T		ui32Alignment,
+									PVRSRV_KERNEL_MEM_INFO	**ppsMemInfo)
+{
+	PVRSRV_KERNEL_MEM_INFO	*psMemInfo;
+	BM_HANDLE 		hBuffer;
+
+	PVRSRV_MEMBLK	*psMemBlock;
+	IMG_BOOL		bBMError;
+
+	PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+	*ppsMemInfo = IMG_NULL;
+
+	if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+					sizeof(PVRSRV_KERNEL_MEM_INFO),
+					(IMG_VOID **)&psMemInfo, IMG_NULL,
+					"Kernel Memory Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"AllocDeviceMem: Failed to alloc memory for block"));
+		return (PVRSRV_ERROR_OUT_OF_MEMORY);
+	}
+
+	OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+
+	psMemBlock = &(psMemInfo->sMemBlk);
+
+
+	psMemInfo->ui32Flags = ui32Flags | PVRSRV_MEM_RAM_BACKED_ALLOCATION;
+
+	bBMError = BM_Alloc (hDevMemHeap,
+							IMG_NULL,
+							ui32Size,
+							&psMemInfo->ui32Flags,
+							IMG_CAST_TO_DEVVADDR_UINT(ui32Alignment),
+							&hBuffer);
+
+	if (!bBMError)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"AllocDeviceMem: BM_Alloc Failed"));
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+
+	psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+	psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+
+	psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+
+
+	psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+
+	psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+
+	psMemInfo->ui32AllocSize = ui32Size;
+
+
+	psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+
+	*ppsMemInfo = psMemInfo;
+
+
+	return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR FreeDeviceMem2(PVRSRV_KERNEL_MEM_INFO *psMemInfo, IMG_BOOL bFromAllocator)
+{
+	BM_HANDLE		hBuffer;
+
+	if (!psMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	hBuffer = psMemInfo->sMemBlk.hBuffer;
+
+
+	if (bFromAllocator)
+		BM_Free(hBuffer, psMemInfo->ui32Flags);
+	else
+		BM_FreeExport(hBuffer, psMemInfo->ui32Flags);
+
+
+	if ((psMemInfo->pvSysBackupBuffer) && bFromAllocator)
+	{
+
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->ui32AllocSize, psMemInfo->pvSysBackupBuffer, IMG_NULL);
+		psMemInfo->pvSysBackupBuffer = IMG_NULL;
+	}
+
+	if (psMemInfo->ui32RefCount == 0)
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+
+	return(PVRSRV_OK);
+}
+
+static PVRSRV_ERROR FreeDeviceMem(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+	BM_HANDLE		hBuffer;
+
+	if (!psMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	hBuffer = psMemInfo->sMemBlk.hBuffer;
+
+
+	BM_Free(hBuffer, psMemInfo->ui32Flags);
+
+	if(psMemInfo->pvSysBackupBuffer)
+	{
+
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->ui32AllocSize, psMemInfo->pvSysBackupBuffer, IMG_NULL);
+		psMemInfo->pvSysBackupBuffer = IMG_NULL;
+	}
+
+	OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+
+	return(PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE					hDevCookie,
+												IMG_HANDLE					hDevMemContext,
+												PVRSRV_KERNEL_SYNC_INFO		**ppsKernelSyncInfo)
+{
+	IMG_HANDLE hSyncDevMemHeap;
+	DEVICE_MEMORY_INFO *psDevMemoryInfo;
+	BM_CONTEXT *pBMContext;
+	PVRSRV_ERROR eError;
+	PVRSRV_KERNEL_SYNC_INFO	*psKernelSyncInfo;
+	PVRSRV_SYNC_DATA *psSyncData;
+
+	eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+						sizeof(PVRSRV_KERNEL_SYNC_INFO),
+						(IMG_VOID **)&psKernelSyncInfo, IMG_NULL,
+						"Kernel Synchronization Info");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	psKernelSyncInfo->ui32RefCount = 0;
+
+
+	pBMContext = (BM_CONTEXT*)hDevMemContext;
+	psDevMemoryInfo = &pBMContext->psDeviceNode->sDevMemoryInfo;
+
+
+	hSyncDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->ui32SyncHeapID].hDevMemHeap;
+
+
+
+
+	eError = AllocDeviceMem(hDevCookie,
+							hSyncDevMemHeap,
+							PVRSRV_MEM_CACHE_CONSISTENT,
+							sizeof(PVRSRV_SYNC_DATA),
+							sizeof(IMG_UINT32),
+							&psKernelSyncInfo->psSyncDataMemInfoKM);
+
+	if (eError != PVRSRV_OK)
+	{
+
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+
+	psKernelSyncInfo->psSyncData = psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
+	psSyncData = psKernelSyncInfo->psSyncData;
+
+	psSyncData->ui32WriteOpsPending = 0;
+	psSyncData->ui32WriteOpsComplete = 0;
+	psSyncData->ui32ReadOpsPending = 0;
+	psSyncData->ui32ReadOpsComplete = 0;
+	psSyncData->ui32LastOpDumpVal = 0;
+	psSyncData->ui32LastReadOpDumpVal = 0;
+
+#if defined(PDUMP)
+	PDUMPMEM(psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM,
+			psKernelSyncInfo->psSyncDataMemInfoKM,
+			0,
+			psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize,
+			PDUMP_FLAGS_CONTINUOUS,
+			MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+#endif
+
+	psKernelSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
+	psKernelSyncInfo->sReadOpsCompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+
+
+	psKernelSyncInfo->psSyncDataMemInfoKM->psKernelSyncInfo = IMG_NULL;
+
+
+	*ppsKernelSyncInfo = psKernelSyncInfo;
+
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO	*psKernelSyncInfo)
+{
+	PVRSRV_ERROR eError;
+
+	if (psKernelSyncInfo->ui32RefCount != 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "oops: sync info ref count not zero at destruction"));
+
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	eError = FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM);
+	(IMG_VOID)OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+
+
+	return eError;
+}
+
+static IMG_VOID freeWrapped(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+	IMG_HANDLE hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem;
+
+
+	if(psMemInfo->sMemBlk.psIntSysPAddr)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+		psMemInfo->sMemBlk.psIntSysPAddr = IMG_NULL;
+	}
+
+	if(hOSWrapMem)
+	{
+		OSReleasePhysPageAddr(hOSWrapMem);
+	}
+}
+
+static PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+										  IMG_UINT32	ui32Param,
+										  IMG_BOOL		bFromAllocator)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+
+	psMemInfo->ui32RefCount--;
+
+
+	if((psMemInfo->ui32Flags & PVRSRV_MEM_EXPORTED) && (bFromAllocator == IMG_TRUE))
+	{
+		IMG_HANDLE hMemInfo = IMG_NULL;
+
+
+		eError = PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+								 &hMemInfo,
+								 psMemInfo,
+								 PVRSRV_HANDLE_TYPE_MEM_INFO);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: can't find exported meminfo in the global handle list"));
+			return eError;
+		}
+
+
+		eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
+									hMemInfo,
+									PVRSRV_HANDLE_TYPE_MEM_INFO);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: PVRSRVReleaseHandle failed for exported meminfo"));
+			return eError;
+		}
+	}
+
+
+	if (psMemInfo->ui32RefCount == 0)
+	{
+		switch(psMemInfo->memType)
+		{
+
+			case PVRSRV_MEMTYPE_WRAPPED:
+				freeWrapped(psMemInfo);
+			case PVRSRV_MEMTYPE_DEVICE:
+				if (psMemInfo->psKernelSyncInfo)
+				{
+					psMemInfo->psKernelSyncInfo->ui32RefCount--;
+
+					if (psMemInfo->psKernelSyncInfo->ui32RefCount == 0)
+					{
+						eError = PVRSRVFreeSyncInfoKM(psMemInfo->psKernelSyncInfo);
+					}
+				}
+			case PVRSRV_MEMTYPE_DEVICECLASS:
+				break;
+			default:
+				PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: Unknown memType"));
+				return PVRSRV_ERROR_GENERIC;
+		}
+	}
+
+
+	return FreeDeviceMem2(psMemInfo, bFromAllocator);
+}
+
+static PVRSRV_ERROR FreeDeviceMemCallBack(IMG_PVOID pvParam,
+										  IMG_UINT32 ui32Param)
+{
+	PVRSRV_KERNEL_MEM_INFO *psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)pvParam;
+
+	return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE				hDevCookie,
+												PVRSRV_KERNEL_MEM_INFO	*psMemInfo)
+{
+	PVRSRV_ERROR eError;
+
+	PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+	if (!psMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if (psMemInfo->sMemBlk.hResItem != IMG_NULL)
+	{
+		eError = ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+	}
+	else
+	{
+
+		eError = FreeDeviceMemCallBack(psMemInfo, 0);
+	}
+
+	return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE					hDevCookie,
+												 PVRSRV_PER_PROCESS_DATA	*psPerProc,
+												 IMG_HANDLE					hDevMemHeap,
+												 IMG_UINT32					ui32Flags,
+												 IMG_SIZE_T					ui32Size,
+												 IMG_SIZE_T					ui32Alignment,
+												 PVRSRV_KERNEL_MEM_INFO		**ppsMemInfo)
+{
+	PVRSRV_KERNEL_MEM_INFO	*psMemInfo;
+	PVRSRV_ERROR 			eError;
+	BM_HEAP					*psBMHeap;
+	IMG_HANDLE				hDevMemContext;
+
+	if (!hDevMemHeap ||
+		(ui32Size == 0))
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+
+	if (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+	{
+		if (((ui32Size % HOST_PAGESIZE()) != 0) ||
+			((ui32Alignment % HOST_PAGESIZE()) != 0))
+		{
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+	}
+
+	eError = AllocDeviceMem(hDevCookie,
+							hDevMemHeap,
+							ui32Flags,
+							ui32Size,
+							ui32Alignment,
+							&psMemInfo);
+
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	if (ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)
+	{
+		psMemInfo->psKernelSyncInfo = IMG_NULL;
+	}
+	else
+	{
+
+
+
+		psBMHeap = (BM_HEAP*)hDevMemHeap;
+		hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
+		eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+									   hDevMemContext,
+									   &psMemInfo->psKernelSyncInfo);
+		if(eError != PVRSRV_OK)
+		{
+			goto free_mainalloc;
+		}
+		psMemInfo->psKernelSyncInfo->ui32RefCount++;
+	}
+
+
+	*ppsMemInfo = psMemInfo;
+
+	if (ui32Flags & PVRSRV_MEM_NO_RESMAN)
+	{
+		psMemInfo->sMemBlk.hResItem = IMG_NULL;
+	}
+	else
+	{
+
+		psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+														RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+														psMemInfo,
+														0,
+														FreeDeviceMemCallBack);
+		if (psMemInfo->sMemBlk.hResItem == IMG_NULL)
+		{
+
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+			goto free_mainalloc;
+		}
+	}
+
+
+	psMemInfo->ui32RefCount++;
+
+	psMemInfo->memType = PVRSRV_MEMTYPE_DEVICE;
+
+
+	return (PVRSRV_OK);
+
+free_mainalloc:
+	FreeDeviceMem(psMemInfo);
+
+	return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE              hDevCookie,
+													  PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+	PVRSRV_ERROR		eError;
+	PVRSRV_DEVICE_NODE	*psDeviceNode = hDevCookie;
+
+	PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+	if (!psMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	eError = ResManDissociateRes(psMemInfo->sMemBlk.hResItem, psDeviceNode->hResManContext);
+
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+	return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFreeDeviceMemKM(IMG_UINT32 ui32Flags,
+												   IMG_SIZE_T *pui32Total,
+												   IMG_SIZE_T *pui32Free,
+												   IMG_SIZE_T *pui32LargestBlock)
+{
+
+
+	PVR_UNREFERENCED_PARAMETER(ui32Flags);
+	PVR_UNREFERENCED_PARAMETER(pui32Total);
+	PVR_UNREFERENCED_PARAMETER(pui32Free);
+	PVR_UNREFERENCED_PARAMETER(pui32LargestBlock);
+
+	return PVRSRV_OK;
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemoryKM (PVRSRV_KERNEL_MEM_INFO	*psMemInfo)
+{
+	if (!psMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+}
+
+
+static PVRSRV_ERROR UnwrapExtMemoryCallBack(IMG_PVOID	pvParam,
+											IMG_UINT32	ui32Param)
+{
+	PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam;
+
+	return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE				hDevCookie,
+												PVRSRV_PER_PROCESS_DATA	*psPerProc,
+												IMG_HANDLE				hDevMemContext,
+												IMG_SIZE_T 				ui32ByteSize,
+												IMG_SIZE_T				ui32PageOffset,
+												IMG_BOOL				bPhysContig,
+												IMG_SYS_PHYADDR	 		*psExtSysPAddr,
+												IMG_VOID 				*pvLinAddr,
+												IMG_UINT32				ui32Flags,
+												PVRSRV_KERNEL_MEM_INFO	**ppsMemInfo)
+{
+	PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL;
+	DEVICE_MEMORY_INFO  *psDevMemoryInfo;
+	IMG_SIZE_T			ui32HostPageSize = HOST_PAGESIZE();
+	IMG_HANDLE			hDevMemHeap = IMG_NULL;
+	PVRSRV_DEVICE_NODE* psDeviceNode;
+	BM_HANDLE 			hBuffer;
+	PVRSRV_MEMBLK		*psMemBlock;
+	IMG_BOOL			bBMError;
+	BM_HEAP				*psBMHeap;
+	PVRSRV_ERROR		eError;
+	IMG_VOID 			*pvPageAlignedCPUVAddr;
+	IMG_SYS_PHYADDR	 	*psIntSysPAddr = IMG_NULL;
+	IMG_HANDLE			hOSWrapMem = IMG_NULL;
+	DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+	IMG_SIZE_T		ui32PageCount = 0;
+	IMG_UINT32		i;
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE*)hDevCookie;
+	PVR_ASSERT(psDeviceNode != IMG_NULL);
+
+	if (psDeviceNode == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: invalid parameter"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if(pvLinAddr)
+	{
+
+		ui32PageOffset = (IMG_UINTPTR_T)pvLinAddr & (ui32HostPageSize - 1);
+
+
+		ui32PageCount = HOST_PAGEALIGN(ui32ByteSize + ui32PageOffset) / ui32HostPageSize;
+		pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvLinAddr - ui32PageOffset);
+
+
+		if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						ui32PageCount * sizeof(IMG_SYS_PHYADDR),
+						(IMG_VOID **)&psIntSysPAddr, IMG_NULL,
+						"Array of Page Addresses") != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		}
+
+		eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr,
+										ui32PageCount * ui32HostPageSize,
+										psIntSysPAddr,
+										&hOSWrapMem,
+										(ui32Flags != 0) ? IMG_TRUE : IMG_FALSE);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+			goto ErrorExitPhase1;
+		}
+
+
+		psExtSysPAddr = psIntSysPAddr;
+
+
+
+		bPhysContig = IMG_FALSE;
+	}
+	else
+	{
+
+	}
+
+
+	psDevMemoryInfo = &((BM_CONTEXT*)hDevMemContext)->psDeviceNode->sDevMemoryInfo;
+	psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+	for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
+	{
+		if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID)
+		{
+			if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
+			{
+
+				hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
+			}
+			else
+			{
+				hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap;
+			}
+			break;
+		}
+	}
+
+	if(hDevMemHeap == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: unable to find mapping heap"));
+		eError = PVRSRV_ERROR_GENERIC;
+		goto ErrorExitPhase2;
+	}
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					sizeof(PVRSRV_KERNEL_MEM_INFO),
+					(IMG_VOID **)&psMemInfo, IMG_NULL,
+					"Kernel Memory Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto ErrorExitPhase2;
+	}
+
+	OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+	psMemInfo->ui32Flags = ui32Flags;
+
+	psMemBlock = &(psMemInfo->sMemBlk);
+
+	bBMError = BM_Wrap(hDevMemHeap,
+					   ui32ByteSize,
+					   ui32PageOffset,
+					   bPhysContig,
+					   psExtSysPAddr,
+					   IMG_NULL,
+					   &psMemInfo->ui32Flags,
+					   &hBuffer);
+	if (!bBMError)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: BM_Wrap Failed"));
+		eError = PVRSRV_ERROR_BAD_MAPPING;
+		goto ErrorExitPhase3;
+	}
+
+
+	psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+	psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+	psMemBlock->hOSWrapMem = hOSWrapMem;
+	psMemBlock->psIntSysPAddr = psIntSysPAddr;
+
+
+	psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+
+	psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+	psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+	psMemInfo->ui32AllocSize = ui32ByteSize;
+
+
+
+	psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+
+
+
+	psBMHeap = (BM_HEAP*)hDevMemHeap;
+	hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
+	eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+									hDevMemContext,
+									&psMemInfo->psKernelSyncInfo);
+	if(eError != PVRSRV_OK)
+	{
+		goto ErrorExitPhase4;
+	}
+
+	psMemInfo->psKernelSyncInfo->ui32RefCount++;
+
+	psMemInfo->memType = PVRSRV_MEMTYPE_WRAPPED;
+
+
+	psMemInfo->ui32RefCount++;
+
+
+	psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+													RESMAN_TYPE_DEVICEMEM_WRAP,
+													psMemInfo,
+													0,
+													UnwrapExtMemoryCallBack);
+
+
+	*ppsMemInfo = psMemInfo;
+
+	return PVRSRV_OK;
+
+
+
+ErrorExitPhase4:
+	if(psMemInfo)
+	{
+		FreeDeviceMem(psMemInfo);
+
+
+
+		psMemInfo = IMG_NULL;
+	}
+
+ErrorExitPhase3:
+	if(psMemInfo)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+	}
+
+ErrorExitPhase2:
+	if(psIntSysPAddr)
+	{
+		OSReleasePhysPageAddr(hOSWrapMem);
+	}
+
+ErrorExitPhase1:
+	if(psIntSysPAddr)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageCount * sizeof(IMG_SYS_PHYADDR), psIntSysPAddr, IMG_NULL);
+
+	}
+
+	return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM (PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+	if (!psMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+}
+
+
+static PVRSRV_ERROR UnmapDeviceMemoryCallBack(IMG_PVOID pvParam,
+											  IMG_UINT32 ui32Param)
+{
+	PVRSRV_ERROR				eError;
+	RESMAN_MAP_DEVICE_MEM_DATA	*psMapData = pvParam;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+	if(psMapData->psMemInfo->sMemBlk.psIntSysPAddr)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psMapData->psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+		psMapData->psMemInfo->sMemBlk.psIntSysPAddr = IMG_NULL;
+	}
+
+	psMapData->psMemInfo->psKernelSyncInfo->ui32RefCount--;
+	if (psMapData->psMemInfo->psKernelSyncInfo->ui32RefCount == 0)
+	{
+		eError = PVRSRVFreeSyncInfoKM(psMapData->psMemInfo->psKernelSyncInfo);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"UnmapDeviceMemoryCallBack: Failed to free sync info"));
+			return eError;
+		}
+	}
+
+	eError = FreeDeviceMem(psMapData->psMemInfo);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"UnmapDeviceMemoryCallBack: Failed to free DST meminfo"));
+		return eError;
+	}
+
+
+	eError = FreeMemCallBackCommon(psMapData->psSrcMemInfo, 0, IMG_FALSE);
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL);
+
+
+	return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+												  PVRSRV_KERNEL_MEM_INFO	*psSrcMemInfo,
+												  IMG_HANDLE				hDstDevMemHeap,
+												  PVRSRV_KERNEL_MEM_INFO	**ppsDstMemInfo)
+{
+	PVRSRV_ERROR				eError;
+	IMG_UINT32					i;
+	IMG_SIZE_T					ui32PageCount, ui32PageOffset;
+	IMG_SIZE_T					ui32HostPageSize = HOST_PAGESIZE();
+	IMG_SYS_PHYADDR				*psSysPAddr = IMG_NULL;
+	IMG_DEV_PHYADDR				sDevPAddr;
+	BM_BUF						*psBuf;
+	IMG_DEV_VIRTADDR			sDevVAddr;
+	PVRSRV_KERNEL_MEM_INFO		*psMemInfo = IMG_NULL;
+	BM_HANDLE 					hBuffer;
+	PVRSRV_MEMBLK				*psMemBlock;
+	IMG_BOOL					bBMError;
+	PVRSRV_DEVICE_NODE			*psDeviceNode;
+	IMG_VOID 					*pvPageAlignedCPUVAddr;
+	RESMAN_MAP_DEVICE_MEM_DATA	*psMapData = IMG_NULL;
+
+
+	if(!psSrcMemInfo || !hDstDevMemHeap || !ppsDstMemInfo)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+
+	*ppsDstMemInfo = IMG_NULL;
+
+	ui32PageOffset = psSrcMemInfo->sDevVAddr.uiAddr & (ui32HostPageSize - 1);
+	ui32PageCount = HOST_PAGEALIGN(psSrcMemInfo->ui32AllocSize + ui32PageOffset) / ui32HostPageSize;
+	pvPageAlignedCPUVAddr = (IMG_VOID *)(psSrcMemInfo->sDevVAddr.uiAddr - ui32PageOffset);
+
+
+
+
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					ui32PageCount*sizeof(IMG_SYS_PHYADDR),
+					(IMG_VOID **)&psSysPAddr, IMG_NULL,
+					"Array of Page Addresses") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	psBuf = psSrcMemInfo->sMemBlk.hBuffer;
+
+
+	psDeviceNode = psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+
+	sDevVAddr.uiAddr = psSrcMemInfo->sDevVAddr.uiAddr - IMG_CAST_TO_DEVVADDR_UINT(ui32PageOffset);
+	for(i=0; i<ui32PageCount; i++)
+	{
+		BM_GetPhysPageAddr(psSrcMemInfo, sDevVAddr, &sDevPAddr);
+
+
+		psSysPAddr[i] = SysDevPAddrToSysPAddr (psDeviceNode->sDevId.eDeviceType, sDevPAddr);
+
+
+		sDevVAddr.uiAddr += IMG_CAST_TO_DEVVADDR_UINT(ui32HostPageSize);
+	}
+
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					sizeof(RESMAN_MAP_DEVICE_MEM_DATA),
+					(IMG_VOID **)&psMapData, IMG_NULL,
+					"Resource Manager Map Data") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc resman map data"));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto ErrorExit;
+	}
+
+
+	if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+					sizeof(PVRSRV_KERNEL_MEM_INFO),
+					(IMG_VOID **)&psMemInfo, IMG_NULL,
+					"Kernel Memory Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block"));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto ErrorExit;
+	}
+
+	OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+	psMemInfo->ui32Flags = psSrcMemInfo->ui32Flags;
+
+	psMemBlock = &(psMemInfo->sMemBlk);
+
+	bBMError = BM_Wrap(hDstDevMemHeap,
+					   psSrcMemInfo->ui32AllocSize,
+					   ui32PageOffset,
+					   IMG_FALSE,
+					   psSysPAddr,
+					   pvPageAlignedCPUVAddr,
+					   &psMemInfo->ui32Flags,
+					   &hBuffer);
+
+	if (!bBMError)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: BM_Wrap Failed"));
+		eError = PVRSRV_ERROR_BAD_MAPPING;
+		goto ErrorExit;
+	}
+
+
+	psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+	psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+
+	psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+
+	psMemBlock->psIntSysPAddr = psSysPAddr;
+
+
+	psMemInfo->pvLinAddrKM = psSrcMemInfo->pvLinAddrKM;
+
+
+	psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+	psMemInfo->ui32AllocSize = psSrcMemInfo->ui32AllocSize;
+	psMemInfo->psKernelSyncInfo = psSrcMemInfo->psKernelSyncInfo;
+
+
+	psMemInfo->psKernelSyncInfo->ui32RefCount++;
+
+
+
+	psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+
+	psMemInfo->ui32RefCount++;
+
+
+	psSrcMemInfo->ui32RefCount++;
+
+
+	BM_Export(psSrcMemInfo->sMemBlk.hBuffer);
+
+	psMemInfo->memType = PVRSRV_MEMTYPE_MAPPED;
+
+
+	psMapData->psMemInfo = psMemInfo;
+	psMapData->psSrcMemInfo = psSrcMemInfo;
+
+
+	psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+													RESMAN_TYPE_DEVICEMEM_MAPPING,
+													psMapData,
+													0,
+													UnmapDeviceMemoryCallBack);
+
+	*ppsDstMemInfo = psMemInfo;
+
+	return PVRSRV_OK;
+
+
+
+ErrorExit:
+
+	if(psSysPAddr)
+	{
+
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psSysPAddr, IMG_NULL);
+
+	}
+
+	if(psMemInfo)
+	{
+
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+	}
+
+	if(psMapData)
+	{
+
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL);
+
+	}
+
+	return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+	if (!psMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+}
+
+
+static PVRSRV_ERROR UnmapDeviceClassMemoryCallBack(IMG_PVOID	pvParam,
+												   IMG_UINT32	ui32Param)
+{
+	PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam;
+
+	return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+													   IMG_HANDLE				hDevMemContext,
+													   IMG_HANDLE				hDeviceClassBuffer,
+													   PVRSRV_KERNEL_MEM_INFO	**ppsMemInfo,
+													   IMG_HANDLE				*phOSMapInfo)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+	PVRSRV_DEVICECLASS_BUFFER *psDeviceClassBuffer;
+	IMG_SYS_PHYADDR *psSysPAddr;
+	IMG_VOID *pvCPUVAddr, *pvPageAlignedCPUVAddr;
+	IMG_BOOL bPhysContig;
+	BM_CONTEXT *psBMContext;
+	DEVICE_MEMORY_INFO *psDevMemoryInfo;
+	DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+	IMG_HANDLE hDevMemHeap = IMG_NULL;
+	IMG_SIZE_T ui32ByteSize;
+	IMG_SIZE_T ui32Offset;
+	IMG_SIZE_T ui32PageSize = HOST_PAGESIZE();
+	BM_HANDLE		hBuffer;
+	PVRSRV_MEMBLK	*psMemBlock;
+	IMG_BOOL		bBMError;
+	IMG_UINT32 i;
+	IMG_BOOL bMapped = IMG_FALSE;
+	
+	if(!hDeviceClassBuffer || !ppsMemInfo || !phOSMapInfo || !hDevMemContext)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDeviceClassBuffer = (PVRSRV_DEVICECLASS_BUFFER*)hDeviceClassBuffer;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	eError = psDeviceClassBuffer->pfnGetBufferAddr(psDeviceClassBuffer->hExtDevice,
+												   psDeviceClassBuffer->hExtBuffer,
+												   &psSysPAddr,
+												   &ui32ByteSize,
+												   &pvCPUVAddr,
+												   phOSMapInfo,
+												   &bPhysContig,
+												   &bMapped);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to get buffer address"));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+
+	psBMContext = (BM_CONTEXT*)psDeviceClassBuffer->hDevMemContext;
+	psDevMemoryInfo = &psBMContext->psDeviceNode->sDevMemoryInfo;
+	psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+	for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
+	{
+		if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID)
+		{
+			if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
+			{
+
+				hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
+			}
+			else
+			{
+				hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap;
+			}
+			break;
+		}
+	}
+
+	if(hDevMemHeap == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to find mapping heap"));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+
+	ui32Offset = ((IMG_UINTPTR_T)pvCPUVAddr) & (ui32PageSize - 1);
+	pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvCPUVAddr - ui32Offset);
+
+	if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+					sizeof(PVRSRV_KERNEL_MEM_INFO),
+					(IMG_VOID **)&psMemInfo, IMG_NULL,
+					"Kernel Memory Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for block"));
+		return (PVRSRV_ERROR_OUT_OF_MEMORY);
+	}
+
+	OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+
+	psMemBlock = &(psMemInfo->sMemBlk);
+
+	bBMError = BM_Wrap(hDevMemHeap,
+					   ui32ByteSize,
+					   ui32Offset,
+					   bPhysContig,
+					   psSysPAddr,
+					   pvPageAlignedCPUVAddr,
+					   &psMemInfo->ui32Flags,
+					   &hBuffer);
+
+	if (!bBMError)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: BM_Wrap Failed"));
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+		return PVRSRV_ERROR_BAD_MAPPING;
+	}
+
+
+	psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+	psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+
+	psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+
+
+	psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+	/* For Buffer Class of Texture Stream. Memory has been already mapped. */
+	if (IMG_FALSE == bMapped) { 
+		psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+	} else {
+		psMemInfo->sDevVAddr.uiAddr = (IMG_UINT32)(psSysPAddr->uiAddr);
+	}
+	
+	psMemInfo->ui32AllocSize = ui32ByteSize;
+	psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo;
+
+
+
+	psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+
+	psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+													RESMAN_TYPE_DEVICECLASSMEM_MAPPING,
+													psMemInfo,
+													0,
+													UnmapDeviceClassMemoryCallBack);
+
+	psMemInfo->ui32RefCount++;
+
+	psMemInfo->memType = PVRSRV_MEMTYPE_DEVICECLASS;
+
+
+	*ppsMemInfo = psMemInfo;
+
+	return PVRSRV_OK;
+}
+
+
+/*
+ * PVRSRVGetPageListKM()
+ *
+ * This is an EMGD addition to PVR services.  Given a PowerVR meminfo,
+ * returns a list of pages for that allocation.  This can then be used
+ * by EMGD code for things like mapping into the GTT if the surface
+ * is going to be displayed.
+ *
+ * Note that the page list returned is the live page list and should
+ * not be modified or freed by the caller.
+ */
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetPageListKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+	struct page ***pvPageList,
+	unsigned long *numpages,
+	unsigned long *offset)
+{
+	LinuxMemArea *ma;
+	unsigned long skippages, total_offset;
+
+	/* Sanity check the parameters */
+	if (!psMemInfo || !pvPageList || !numpages) {
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	ma = (LinuxMemArea*)psMemInfo->sMemBlk.hOSMemHandle;
+
+	/* # of pages isn't stored; needs to be calculated from number of bytes */
+	*numpages = (ma->ui32ByteSize + 4095) / 4096;
+
+	/*
+	 * What type of memarea is this?  We can handle ALLOC_PAGES, or SUB_ALLOC
+	 * areas whose earliest ancestor is an ALLOC_PAGES.
+	 */
+	switch (ma->eAreaType) {
+	case LINUX_MEM_AREA_ALLOC_PAGES:
+		*pvPageList = ma->uData.sPageList.pvPageList;
+		*offset = 0;
+		break;
+	case LINUX_MEM_AREA_SUB_ALLOC:
+		/*
+		 * This allocation may be a subarea of a larger allocation.  We'll need to
+		 * figure out the details of the parent allocation first so that we can
+		 * calculate our subset of the page list and appropriate offset into the
+		 * first page.
+		 */
+		total_offset = 0;
+		while (ma->eAreaType == LINUX_MEM_AREA_SUB_ALLOC) {
+			total_offset += ma->uData.sSubAlloc.ui32ByteOffset;
+			ma = ma->uData.sSubAlloc.psParentLinuxMemArea;
+		}
+
+		/*
+		 * We should now have the original ALLOC_PAGES memarea.  Make sure
+		 * it's actually the type we expect.
+		 */
+		if (ma->eAreaType != LINUX_MEM_AREA_ALLOC_PAGES) {
+			PVR_DPF((PVR_DBG_ERROR,
+				"PVRSRVGetPageListKM: meminfo for suballocation did not "
+				"originate from a a page-based allocation (type=%d)",
+				ma->eAreaType));
+			*numpages = 0;
+			return PVRSRV_ERROR_GENERIC;
+		}
+
+		/*
+		 * After taking all nested suballocations into account, figure out
+		 * where in the page list the allocation we care about really starts.
+		 */
+		skippages = total_offset / 4096;
+		*offset = total_offset % 4096;
+		*pvPageList = &(ma->uData.sPageList.pvPageList)[skippages];
+
+		break;
+
+	default:
+		PVR_DPF((PVR_DBG_ERROR,
+			"PVRSRVGetPageListKM: meminfo not a page-based allocation or sub-allocation (type=%d)",
+			ma->eAreaType));
+		*numpages = 0;
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	return PVRSRV_OK;
+}
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/handle.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/handle.c
new file mode 100644
index 0000000..bfbd6b3
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/handle.c
@@ -0,0 +1,1545 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifdef	PVR_SECURE_HANDLES
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "handle.h"
+
+#ifdef	DEBUG
+#define	HANDLE_BLOCK_SIZE	1
+#else
+#define	HANDLE_BLOCK_SIZE	256
+#endif
+
+#define	HANDLE_HASH_TAB_INIT_SIZE	32
+
+#define	DEFAULT_MAX_INDEX_PLUS_ONE	0xfffffffful
+#define	DEFAULT_MAX_HANDLE		DEFAULT_MAX_INDEX_PLUS_ONE
+
+#define	INDEX_IS_VALID(psBase, i) ((i) < (psBase)->ui32TotalHandCount)
+
+#define	INDEX_TO_HANDLE(psBase, idx) ((IMG_HANDLE)((idx) + 1))
+#define	HANDLE_TO_INDEX(psBase, hand) ((IMG_UINT32)(hand) - 1)
+
+#define INDEX_TO_HANDLE_PTR(psBase, i) (((psBase)->psHandleArray) + (i))
+#define	HANDLE_TO_HANDLE_PTR(psBase, h) (INDEX_TO_HANDLE_PTR(psBase, HANDLE_TO_INDEX(psBase, h)))
+
+#define	HANDLE_PTR_TO_INDEX(psBase, psHandle) (IMG_UINT32)((psHandle) - ((psBase)->psHandleArray))
+#define	HANDLE_PTR_TO_HANDLE(psBase, psHandle) \
+	INDEX_TO_HANDLE(psBase, HANDLE_PTR_TO_INDEX(psBase, psHandle))
+
+#define	ROUND_UP_TO_MULTIPLE(a, b) ((((a) + (b) - 1) / (b)) * (b))
+
+#define	HANDLES_BATCHED(psBase) ((psBase)->ui32HandBatchSize != 0)
+
+#define	SET_FLAG(v, f) ((IMG_VOID)((v) |= (f)))
+#define	CLEAR_FLAG(v, f) ((IMG_VOID)((v) &= ~(f)))
+#define	TEST_FLAG(v, f) ((IMG_BOOL)(((v) & (f)) != 0))
+
+#define	TEST_ALLOC_FLAG(psHandle, f) TEST_FLAG((psHandle)->eFlag, f)
+
+#define	SET_INTERNAL_FLAG(psHandle, f) SET_FLAG((psHandle)->eInternalFlag, f)
+#define	CLEAR_INTERNAL_FLAG(psHandle, f) CLEAR_FLAG((psHandle)->eInternalFlag, f)
+#define	TEST_INTERNAL_FLAG(psHandle, f) TEST_FLAG((psHandle)->eInternalFlag, f)
+
+#define	BATCHED_HANDLE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define	SET_BATCHED_HANDLE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define	SET_UNBATCHED_HANDLE(psHandle) CLEAR_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define	BATCHED_HANDLE_PARTIALLY_FREE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
+
+#define SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
+
+#define	HANDLE_STRUCT_IS_FREE(psHandle) ((psHandle)->eType == PVRSRV_HANDLE_TYPE_NONE && (psHandle)->eInternalFlag == INTERNAL_HANDLE_FLAG_NONE)
+
+#ifdef	MIN
+#undef MIN
+#endif
+
+#define	MIN(x, y) (((x) < (y)) ? (x) : (y))
+
+struct sHandleList
+{
+	IMG_UINT32 ui32Prev;
+	IMG_UINT32 ui32Next;
+	IMG_HANDLE hParent;
+};
+
+enum ePVRSRVInternalHandleFlag
+{
+	INTERNAL_HANDLE_FLAG_NONE = 0x00,
+	INTERNAL_HANDLE_FLAG_BATCHED = 0x01,
+	INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE = 0x02,
+};
+
+struct sHandle
+{
+
+	PVRSRV_HANDLE_TYPE eType;
+
+
+	IMG_VOID *pvData;
+
+
+	IMG_UINT32 ui32NextIndexPlusOne;
+
+
+	enum ePVRSRVInternalHandleFlag eInternalFlag;
+
+
+	PVRSRV_HANDLE_ALLOC_FLAG eFlag;
+
+
+	IMG_UINT32 ui32Index;
+
+
+	struct sHandleList sChildren;
+
+
+	struct sHandleList sSiblings;
+};
+
+struct _PVRSRV_HANDLE_BASE_
+{
+
+	IMG_HANDLE hBaseBlockAlloc;
+
+
+	IMG_HANDLE hHandBlockAlloc;
+
+
+	struct sHandle *psHandleArray;
+
+
+	HASH_TABLE *psHashTab;
+
+
+	IMG_UINT32 ui32FreeHandCount;
+
+
+	IMG_UINT32 ui32FirstFreeIndex;
+
+
+	IMG_UINT32 ui32MaxIndexPlusOne;
+
+
+	IMG_UINT32 ui32TotalHandCount;
+
+
+	IMG_UINT32 ui32LastFreeIndexPlusOne;
+
+
+	IMG_UINT32 ui32HandBatchSize;
+
+
+	IMG_UINT32 ui32TotalHandCountPreBatch;
+
+
+	IMG_UINT32 ui32FirstBatchIndexPlusOne;
+
+
+	IMG_UINT32 ui32BatchHandAllocFailures;
+
+
+	IMG_BOOL bPurgingEnabled;
+};
+
+enum eHandKey {
+	HAND_KEY_DATA = 0,
+	HAND_KEY_TYPE,
+	HAND_KEY_PARENT,
+	HAND_KEY_LEN
+};
+
+PVRSRV_HANDLE_BASE *gpsKernelHandleBase = IMG_NULL;
+
+typedef IMG_UINTPTR_T HAND_KEY[HAND_KEY_LEN];
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListInit)
+#endif
+static INLINE
+IMG_VOID HandleListInit(IMG_UINT32 ui32Index, struct sHandleList *psList, IMG_HANDLE hParent)
+{
+	psList->ui32Next = ui32Index;
+	psList->ui32Prev = ui32Index;
+	psList->hParent = hParent;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitParentList)
+#endif
+static INLINE
+IMG_VOID InitParentList(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+	IMG_UINT32 ui32Parent = HANDLE_PTR_TO_INDEX(psBase, psHandle);
+
+	HandleListInit(ui32Parent, &psHandle->sChildren, INDEX_TO_HANDLE(psBase, ui32Parent));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitChildEntry)
+#endif
+static INLINE
+IMG_VOID InitChildEntry(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+	HandleListInit(HANDLE_PTR_TO_INDEX(psBase, psHandle), &psHandle->sSiblings, IMG_NULL);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListIsEmpty)
+#endif
+static INLINE
+IMG_BOOL HandleListIsEmpty(IMG_UINT32 ui32Index, struct sHandleList *psList)
+{
+	IMG_BOOL bIsEmpty;
+
+	bIsEmpty = (IMG_BOOL)(psList->ui32Next == ui32Index);
+
+#ifdef	DEBUG
+	{
+		IMG_BOOL bIsEmpty2;
+
+		bIsEmpty2 = (IMG_BOOL)(psList->ui32Prev == ui32Index);
+		PVR_ASSERT(bIsEmpty == bIsEmpty2);
+	}
+#endif
+
+	return bIsEmpty;
+}
+
+#ifdef DEBUG
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NoChildren)
+#endif
+static INLINE
+IMG_BOOL NoChildren(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+	PVR_ASSERT(psHandle->sChildren.hParent == HANDLE_PTR_TO_HANDLE(psBase, psHandle));
+
+	return HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psBase, psHandle), &psHandle->sChildren);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NoParent)
+#endif
+static INLINE
+IMG_BOOL NoParent(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+	if (HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psBase, psHandle), &psHandle->sSiblings))
+	{
+		PVR_ASSERT(psHandle->sSiblings.hParent == IMG_NULL);
+
+		return IMG_TRUE;
+	}
+	else
+	{
+		PVR_ASSERT(psHandle->sSiblings.hParent != IMG_NULL);
+	}
+	return IMG_FALSE;
+}
+#endif
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ParentHandle)
+#endif
+static INLINE
+IMG_HANDLE ParentHandle(struct sHandle *psHandle)
+{
+	return psHandle->sSiblings.hParent;
+}
+
+#define	LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, i, p, po, eo) \
+		((struct sHandleList *)((IMG_CHAR *)(INDEX_TO_HANDLE_PTR(psBase, i)) + (((i) == (p)) ? (po) : (eo))))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListInsertBefore)
+#endif
+static INLINE
+IMG_VOID HandleListInsertBefore(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32InsIndex, struct sHandleList *psIns, IMG_SIZE_T uiParentOffset, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_UINT32 ui32ParentIndex)
+{
+
+	struct sHandleList *psPrevIns = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psIns->ui32Prev, ui32ParentIndex, uiParentOffset, uiEntryOffset);
+
+	PVR_ASSERT(psEntry->hParent == IMG_NULL);
+	PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next);
+	PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset, uiParentOffset)->hParent == INDEX_TO_HANDLE(psBase, ui32ParentIndex));
+
+	psEntry->ui32Prev = psIns->ui32Prev;
+	psIns->ui32Prev = ui32EntryIndex;
+	psEntry->ui32Next = ui32InsIndex;
+	psPrevIns->ui32Next = ui32EntryIndex;
+
+	psEntry->hParent = INDEX_TO_HANDLE(psBase, ui32ParentIndex);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(AdoptChild)
+#endif
+static INLINE
+IMG_VOID AdoptChild(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, struct sHandle *psChild)
+{
+	IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psBase, psParent->sChildren.hParent);
+
+	PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psBase, psParent));
+
+	HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren, offsetof(struct sHandle, sChildren), HANDLE_PTR_TO_INDEX(psBase, psChild), &psChild->sSiblings, offsetof(struct sHandle, sSiblings), ui32Parent);
+
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListRemove)
+#endif
+static INLINE
+IMG_VOID HandleListRemove(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_SIZE_T uiParentOffset)
+{
+	if (!HandleListIsEmpty(ui32EntryIndex, psEntry))
+	{
+
+		struct sHandleList *psPrev = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Prev, HANDLE_TO_INDEX(psBase, psEntry->hParent), uiParentOffset, uiEntryOffset);
+		struct sHandleList *psNext = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next, HANDLE_TO_INDEX(psBase, psEntry->hParent), uiParentOffset, uiEntryOffset);
+
+
+		PVR_ASSERT(psEntry->hParent != IMG_NULL);
+
+		psPrev->ui32Next = psEntry->ui32Next;
+		psNext->ui32Prev = psEntry->ui32Prev;
+
+		HandleListInit(ui32EntryIndex, psEntry, IMG_NULL);
+	}
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(UnlinkFromParent)
+#endif
+static INLINE
+IMG_VOID UnlinkFromParent(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+	HandleListRemove(psBase, HANDLE_PTR_TO_INDEX(psBase, psHandle), &psHandle->sSiblings, offsetof(struct sHandle, sSiblings), offsetof(struct sHandle, sChildren));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListIterate)
+#endif
+static INLINE
+PVRSRV_ERROR HandleListIterate(PVRSRV_HANDLE_BASE *psBase, struct sHandleList *psHead, IMG_SIZE_T uiParentOffset, IMG_SIZE_T uiEntryOffset, PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, struct sHandle *))
+{
+	IMG_UINT32 ui32Index;
+	IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psBase, psHead->hParent);
+
+	PVR_ASSERT(psHead->hParent != IMG_NULL);
+
+
+	for(ui32Index = psHead->ui32Next; ui32Index != ui32Parent; )
+	{
+		struct sHandle *psHandle = INDEX_TO_HANDLE_PTR(psBase, ui32Index);
+
+		struct sHandleList *psEntry = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32Index, ui32Parent, uiParentOffset, uiEntryOffset);
+		PVRSRV_ERROR eError;
+
+		PVR_ASSERT(psEntry->hParent == psHead->hParent);
+
+		ui32Index = psEntry->ui32Next;
+
+		eError = (*pfnIterFunc)(psBase, psHandle);
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(IterateOverChildren)
+#endif
+static INLINE
+PVRSRV_ERROR IterateOverChildren(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, struct sHandle *))
+{
+	 return HandleListIterate(psBase, &psParent->sChildren, offsetof(struct sHandle, sChildren), offsetof(struct sHandle, sSiblings), pfnIterFunc);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(GetHandleStructure)
+#endif
+static INLINE
+PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **ppsHandle, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	IMG_UINT32 ui32Index = HANDLE_TO_INDEX(psBase, hHandle);
+	struct sHandle *psHandle;
+
+
+	if (!INDEX_IS_VALID(psBase, ui32Index))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle index out of range (%u >= %u)", ui32Index, psBase->ui32TotalHandCount));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	psHandle =  INDEX_TO_HANDLE_PTR(psBase, ui32Index);
+	if (psHandle->eType == PVRSRV_HANDLE_TYPE_NONE)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle not allocated (index: %u)", ui32Index));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+
+	if (eType != PVRSRV_HANDLE_TYPE_NONE && eType != psHandle->eType)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle type mismatch (%d != %d)", eType, psHandle->eType));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+
+	*ppsHandle = psHandle;
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ParentIfPrivate)
+#endif
+static INLINE
+IMG_HANDLE ParentIfPrivate(struct sHandle *psHandle)
+{
+	return TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
+			ParentHandle(psHandle) : IMG_NULL;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitKey)
+#endif
+static INLINE
+IMG_VOID InitKey(HAND_KEY aKey, PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	aKey[HAND_KEY_DATA] = (IMG_UINTPTR_T)pvData;
+	aKey[HAND_KEY_TYPE] = (IMG_UINTPTR_T)eType;
+	aKey[HAND_KEY_PARENT] = (IMG_UINTPTR_T)hParent;
+}
+
+static PVRSRV_ERROR FreeHandleArray(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if (psBase->psHandleArray != IMG_NULL)
+	{
+		eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+			psBase->ui32TotalHandCount * sizeof(struct sHandle),
+			psBase->psHandleArray,
+			psBase->hHandBlockAlloc);
+
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "FreeHandleArray: Error freeing memory (%d)", eError));
+		}
+		else
+		{
+			psBase->psHandleArray = IMG_NULL;
+		}
+	}
+
+	return eError;
+}
+
+static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+	HAND_KEY aKey;
+	IMG_UINT32 ui32Index = HANDLE_PTR_TO_INDEX(psBase, psHandle);
+	PVRSRV_ERROR eError;
+
+
+	InitKey(aKey, psBase, psHandle->pvData, psHandle->eType, ParentIfPrivate(psHandle));
+
+	if (!TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_MULTI) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+	{
+		IMG_HANDLE hHandle;
+		hHandle = (IMG_HANDLE) HASH_Remove_Extended(psBase->psHashTab, aKey);
+
+		PVR_ASSERT(hHandle != IMG_NULL);
+		PVR_ASSERT(hHandle == INDEX_TO_HANDLE(psBase, ui32Index));
+		PVR_UNREFERENCED_PARAMETER(hHandle);
+	}
+
+
+	UnlinkFromParent(psBase, psHandle);
+
+
+	eError = IterateOverChildren(psBase, psHandle, FreeHandle);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreeHandle: Error whilst freeing subhandles (%d)", eError));
+		return eError;
+	}
+
+
+	psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
+
+	if (BATCHED_HANDLE(psHandle) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+	{
+
+		SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle);
+
+		return PVRSRV_OK;
+	}
+
+
+	if (!psBase->bPurgingEnabled)
+	{
+		if (psBase->ui32FreeHandCount == 0)
+		{
+			PVR_ASSERT(psBase->ui32FirstFreeIndex == 0);
+			PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
+
+			psBase->ui32FirstFreeIndex =  ui32Index;
+		}
+		else
+		{
+
+			PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
+			PVR_ASSERT(INDEX_TO_HANDLE_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
+			INDEX_TO_HANDLE_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne =  ui32Index + 1;
+		}
+
+		PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0);
+
+
+		psBase->ui32LastFreeIndexPlusOne = ui32Index + 1;
+	}
+
+	psBase->ui32FreeHandCount++;
+
+	return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+	IMG_UINT32 i;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
+	{
+		return eError;
+	}
+
+	for (i = 0; i < psBase->ui32TotalHandCount; i++)
+	{
+		struct sHandle *psHandle;
+
+		psHandle = INDEX_TO_HANDLE_PTR(psBase, i);
+
+		if (psHandle->eType != PVRSRV_HANDLE_TYPE_NONE)
+		{
+			eError = FreeHandle(psBase, psHandle);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "FreeAllHandles: FreeHandle failed (%d)", eError));
+				break;
+			}
+
+
+			if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
+			{
+				break;
+			}
+		}
+	}
+
+	return eError;
+}
+
+static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVRSRV_ERROR eError;
+
+	if (HANDLES_BATCHED(psBase))
+	{
+		PVR_DPF((PVR_DBG_WARNING, "FreeHandleBase: Uncommitted/Unreleased handle batch"));
+		PVRSRVReleaseHandleBatch(psBase);
+	}
+
+
+	eError = FreeAllHandles(psBase);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handles (%d)", eError));
+		return eError;
+	}
+
+
+	eError = FreeHandleArray(psBase);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle array (%d)", eError));
+		return eError;
+	}
+
+	if (psBase->psHashTab != IMG_NULL)
+	{
+
+		HASH_Delete(psBase->psHashTab);
+	}
+
+	eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+		sizeof(*psBase),
+		psBase,
+		psBase->hBaseBlockAlloc);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle base (%d)", eError));
+		return eError;
+	}
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(FindHandle)
+#endif
+static INLINE
+IMG_HANDLE FindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
+{
+	HAND_KEY aKey;
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	InitKey(aKey, psBase, pvData, eType, hParent);
+
+	return (IMG_HANDLE) HASH_Retrieve_Extended(psBase->psHashTab, aKey);
+}
+
+static PVRSRV_ERROR ReallocMem(IMG_PVOID *ppvMem, IMG_HANDLE *phBlockAlloc, IMG_UINT32 ui32NewSize, IMG_UINT32 ui32OldSize)
+{
+	IMG_VOID *pvOldMem = *ppvMem;
+	IMG_HANDLE hOldBlockAlloc = *phBlockAlloc;
+	IMG_UINT32 ui32CopySize = MIN(ui32NewSize, ui32OldSize);
+	IMG_VOID *pvNewMem = IMG_NULL;
+	IMG_HANDLE hNewBlockAlloc = IMG_NULL;
+	PVRSRV_ERROR eError;
+
+	if (ui32NewSize == ui32OldSize)
+	{
+		return (PVRSRV_OK);
+	}
+
+	if (ui32NewSize != 0)
+	{
+
+		eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+			ui32NewSize,
+			&pvNewMem,
+			&hNewBlockAlloc,
+			"Memory Area");
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "ReallocMem: Couldn't allocate new memory area (%d)", eError));
+			return eError;
+		}
+	}
+
+	if (ui32CopySize != 0)
+	{
+
+		OSMemCopy(pvNewMem, pvOldMem, ui32CopySize);
+	}
+
+	if (ui32OldSize != 0)
+	{
+
+		eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				ui32OldSize,
+				pvOldMem,
+				hOldBlockAlloc);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "ReallocMem: Couldn't free old memory area (%d)", eError));
+		}
+	}
+
+	*ppvMem = pvNewMem;
+	*phBlockAlloc = hNewBlockAlloc;
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ReallocHandleArray)
+#endif
+static INLINE
+PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCount, IMG_UINT32 ui32OldCount)
+{
+	return ReallocMem((IMG_PVOID *)&psBase->psHandleArray,
+				&psBase->hHandBlockAlloc,
+				ui32NewCount * sizeof(struct sHandle),
+				ui32OldCount * sizeof(struct sHandle));
+}
+
+static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Delta)
+{
+	PVRSRV_ERROR eError;
+	struct sHandle *psHandle;
+	IMG_UINT32 ui32DeltaAdjusted = ROUND_UP_TO_MULTIPLE(ui32Delta, HANDLE_BLOCK_SIZE);
+	IMG_UINT32 ui32NewTotalHandCount = psBase->ui32TotalHandCount + ui32DeltaAdjusted;
+;
+
+	PVR_ASSERT(ui32Delta != 0);
+
+
+	if (ui32NewTotalHandCount > psBase->ui32MaxIndexPlusOne || ui32NewTotalHandCount <= psBase->ui32TotalHandCount)
+	{
+		ui32NewTotalHandCount = psBase->ui32MaxIndexPlusOne;
+
+		ui32DeltaAdjusted = ui32NewTotalHandCount - psBase->ui32TotalHandCount;
+
+		if (ui32DeltaAdjusted < ui32Delta)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: Maximum handle limit reached (%d)", psBase->ui32MaxIndexPlusOne));
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		}
+	}
+
+	PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta);
+
+
+	eError = ReallocHandleArray(psBase, ui32NewTotalHandCount, psBase->ui32TotalHandCount);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: ReallocHandleArray failed (%d)", eError));
+		return eError;
+	}
+
+
+	for(psHandle = psBase->psHandleArray + psBase->ui32TotalHandCount;
+		psHandle < psBase->psHandleArray + ui32NewTotalHandCount;
+		psHandle++)
+	{
+		psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
+		psHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
+		psHandle->ui32NextIndexPlusOne  = 0;
+	}
+
+
+	psBase->ui32FreeHandCount += ui32DeltaAdjusted;
+
+	if (psBase->ui32FirstFreeIndex == 0)
+	{
+		PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
+
+		psBase->ui32FirstFreeIndex = psBase->ui32TotalHandCount;
+	}
+	else
+	{
+		if (!psBase->bPurgingEnabled)
+		{
+			PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0)
+			PVR_ASSERT(INDEX_TO_HANDLE_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
+
+			INDEX_TO_HANDLE_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = psBase->ui32TotalHandCount + 1;
+		}
+	}
+
+	if (!psBase->bPurgingEnabled)
+	{
+		psBase->ui32LastFreeIndexPlusOne = ui32NewTotalHandCount;
+	}
+
+	psBase->ui32TotalHandCount = ui32NewTotalHandCount;
+
+	return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR EnsureFreeHandles(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Free)
+{
+	PVRSRV_ERROR eError;
+
+	if (ui32Free > psBase->ui32FreeHandCount)
+	{
+		IMG_UINT32 ui32FreeHandDelta = ui32Free - psBase->ui32FreeHandCount;
+		eError = IncreaseHandleArraySize(psBase, ui32FreeHandDelta);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "EnsureFreeHandles: Couldn't allocate %u handles to ensure %u free handles (IncreaseHandleArraySize failed with error %d)", ui32FreeHandDelta, ui32Free, eError));
+
+			return eError;
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+	IMG_UINT32 ui32NewIndex;
+	struct sHandle *psNewHandle = IMG_NULL;
+	IMG_HANDLE hHandle;
+	HAND_KEY aKey;
+	PVRSRV_ERROR eError;
+
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	PVR_ASSERT(psBase->psHashTab != IMG_NULL);
+
+	if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+	{
+
+		PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == IMG_NULL);
+	}
+
+	if (psBase->ui32FreeHandCount == 0 && HANDLES_BATCHED(psBase))
+	{
+		 PVR_DPF((PVR_DBG_WARNING, "AllocHandle: Handle batch size (%u) was too small, allocating additional space", psBase->ui32HandBatchSize));
+	}
+
+
+	eError = EnsureFreeHandles(psBase, 1);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "AllocHandle: EnsureFreeHandles failed (%d)", eError));
+		return eError;
+	}
+	PVR_ASSERT(psBase->ui32FreeHandCount != 0)
+
+	if (!psBase->bPurgingEnabled)
+	{
+
+		ui32NewIndex = psBase->ui32FirstFreeIndex;
+
+
+		psNewHandle = INDEX_TO_HANDLE_PTR(psBase, ui32NewIndex);
+	}
+	else
+	{
+
+		for(ui32NewIndex = psBase->ui32FirstFreeIndex; ui32NewIndex < psBase->ui32TotalHandCount; ui32NewIndex++)
+		{
+			psNewHandle = INDEX_TO_HANDLE_PTR(psBase, ui32NewIndex);
+			if (HANDLE_STRUCT_IS_FREE(psNewHandle))
+			{
+				break;
+			}
+
+		}
+		psBase->ui32FirstFreeIndex = 0;
+		PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount);
+	}
+	PVR_ASSERT(psNewHandle != IMG_NULL);
+
+
+	hHandle = INDEX_TO_HANDLE(psBase, ui32NewIndex);
+
+
+	if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+	{
+
+		InitKey(aKey, psBase, pvData, eType, hParent);
+
+
+		if (!HASH_Insert_Extended(psBase->psHashTab, aKey, (IMG_UINTPTR_T)hHandle))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't add handle to hash table"));
+
+			return PVRSRV_ERROR_GENERIC;
+		}
+	}
+
+	psBase->ui32FreeHandCount--;
+
+
+	if (!psBase->bPurgingEnabled)
+	{
+
+		if (psBase->ui32FreeHandCount == 0)
+		{
+			PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex);
+			PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1));
+
+			psBase->ui32LastFreeIndexPlusOne = 0;
+			psBase->ui32FirstFreeIndex = 0;
+		}
+		else
+		{
+
+			psBase->ui32FirstFreeIndex = (psNewHandle->ui32NextIndexPlusOne == 0) ?
+				ui32NewIndex + 1 :
+				psNewHandle->ui32NextIndexPlusOne - 1;
+		}
+	}
+
+
+	psNewHandle->eType = eType;
+	psNewHandle->pvData = pvData;
+	psNewHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
+	psNewHandle->eFlag = eFlag;
+	psNewHandle->ui32Index = ui32NewIndex;
+
+	InitParentList(psBase, psNewHandle);
+#if defined(DEBUG)
+	PVR_ASSERT(NoChildren(psBase, psNewHandle));
+#endif
+
+	InitChildEntry(psBase, psNewHandle);
+#if defined(DEBUG)
+	PVR_ASSERT(NoParent(psBase, psNewHandle));
+#endif
+
+	if (HANDLES_BATCHED(psBase))
+	{
+
+		psNewHandle->ui32NextIndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
+
+		psBase->ui32FirstBatchIndexPlusOne = ui32NewIndex + 1;
+
+
+		SET_BATCHED_HANDLE(psNewHandle);
+	}
+	else
+	{
+		psNewHandle->ui32NextIndexPlusOne = 0;
+	}
+
+
+	*phHandle = hHandle;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+{
+	IMG_HANDLE hHandle;
+	PVRSRV_ERROR eError;
+
+	*phHandle = IMG_NULL;
+
+	if (HANDLES_BATCHED(psBase))
+	{
+
+		psBase->ui32BatchHandAllocFailures++;
+	}
+
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+	{
+
+		hHandle = FindHandle(psBase, pvData, eType, IMG_NULL);
+		if (hHandle != IMG_NULL)
+		{
+			struct sHandle *psHandle;
+
+			eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Lookup of existing handle failed"));
+				return eError;
+			}
+
+
+			if (TEST_FLAG(psHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED))
+			{
+				*phHandle = hHandle;
+				eError = PVRSRV_OK;
+				goto exit_ok;
+			}
+			return PVRSRV_ERROR_GENERIC;
+		}
+	}
+
+	eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, IMG_NULL);
+
+exit_ok:
+	if (HANDLES_BATCHED(psBase) && (eError == PVRSRV_OK))
+	{
+		psBase->ui32BatchHandAllocFailures--;
+	}
+
+	return eError;
+}
+
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+	struct sHandle *psPHand;
+	struct sHandle *psCHand;
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hParentKey;
+	IMG_HANDLE hHandle;
+
+	*phHandle = IMG_NULL;
+
+	if (HANDLES_BATCHED(psBase))
+	{
+
+		psBase->ui32BatchHandAllocFailures++;
+	}
+
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
+			hParent : IMG_NULL;
+
+
+	eError = GetHandleStructure(psBase, &psPHand, hParent, PVRSRV_HANDLE_TYPE_NONE);
+	if (eError != PVRSRV_OK)
+	{
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+	{
+
+		hHandle = FindHandle(psBase, pvData, eType, hParentKey);
+		if (hHandle != IMG_NULL)
+		{
+			struct sHandle *psCHandle;
+			PVRSRV_ERROR eErr;
+
+			eErr = GetHandleStructure(psBase, &psCHandle, hHandle, eType);
+			if (eErr != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Lookup of existing handle failed"));
+				return eErr;
+			}
+
+			PVR_ASSERT(hParentKey != IMG_NULL && ParentHandle(HANDLE_TO_HANDLE_PTR(psBase, hHandle)) == hParent);
+
+
+			if (TEST_FLAG(psCHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED) && ParentHandle(HANDLE_TO_HANDLE_PTR(psBase, hHandle)) == hParent)
+			{
+				*phHandle = hHandle;
+				goto exit_ok;
+			}
+			return PVRSRV_ERROR_GENERIC;
+		}
+	}
+
+	eError = AllocHandle(psBase, &hHandle, pvData, eType, eFlag, hParentKey);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+
+	psPHand = HANDLE_TO_HANDLE_PTR(psBase, hParent);
+
+	psCHand = HANDLE_TO_HANDLE_PTR(psBase, hHandle);
+
+	AdoptChild(psBase, psPHand, psCHand);
+
+	*phHandle = hHandle;
+
+exit_ok:
+	if (HANDLES_BATCHED(psBase))
+	{
+		psBase->ui32BatchHandAllocFailures--;
+	}
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
+{
+	IMG_HANDLE hHandle;
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+
+	hHandle = (IMG_HANDLE) FindHandle(psBase, pvData, eType, IMG_NULL);
+	if (hHandle == IMG_NULL)
+	{
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	*phHandle = hHandle;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
+{
+	struct sHandle *psHandle;
+	PVRSRV_ERROR eError;
+
+	eError = GetHandleStructure(psBase, &psHandle, hHandle, PVRSRV_HANDLE_TYPE_NONE);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandleAnyType: Error looking up handle (%d)", eError));
+		return eError;
+	}
+
+	*ppvData = psHandle->pvData;
+	*peType = psHandle->eType;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	struct sHandle *psHandle;
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandle: Error looking up handle (%d)", eError));
+		return eError;
+	}
+
+	*ppvData = psHandle->pvData;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor)
+{
+	struct sHandle *psPHand;
+	struct sHandle *psCHand;
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	eError = GetHandleStructure(psBase, &psCHand, hHandle, eType);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Error looking up subhandle (%d)", eError));
+		return eError;
+	}
+
+
+	for (psPHand = psCHand; ParentHandle(psPHand) != hAncestor; )
+	{
+		eError = GetHandleStructure(psBase, &psPHand, ParentHandle(psPHand), PVRSRV_HANDLE_TYPE_NONE);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Subhandle doesn't belong to given ancestor"));
+			return PVRSRV_ERROR_GENERIC;
+		}
+	}
+
+	*ppvData = psCHand->pvData;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	struct sHandle *psHandle;
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetParentHandle: Error looking up subhandle (%d)", eError));
+		return eError;
+	}
+
+	*phParent = ParentHandle(psHandle);
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	struct sHandle *psHandle;
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupAndReleaseHandle: Error looking up handle (%d)", eError));
+		return eError;
+	}
+
+	*ppvData = psHandle->pvData;
+
+	eError = FreeHandle(psBase, psHandle);
+
+	return eError;
+}
+
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	struct sHandle *psHandle;
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVReleaseHandle: Error looking up handle (%d)", eError));
+		return eError;
+	}
+
+	eError = FreeHandle(psBase, psHandle);
+
+	return eError;
+}
+
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
+{
+	PVRSRV_ERROR eError;
+
+	if (HANDLES_BATCHED(psBase))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: There is a handle batch already in use (size %u)", psBase->ui32HandBatchSize));
+		return  PVRSRV_ERROR_GENERIC;
+	}
+
+	if (ui32BatchSize == 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: Invalid batch size (%u)", ui32BatchSize));
+		return  PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	eError = EnsureFreeHandles(psBase, ui32BatchSize);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: EnsureFreeHandles failed (error %d)", eError));
+		return eError;
+	}
+
+	psBase->ui32HandBatchSize = ui32BatchSize;
+
+
+	psBase->ui32TotalHandCountPreBatch = psBase->ui32TotalHandCount;
+
+	PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0);
+
+	PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0);
+
+	PVR_ASSERT(HANDLES_BATCHED(psBase));
+
+	return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, IMG_BOOL bCommit)
+{
+
+	IMG_UINT32 ui32IndexPlusOne;
+	IMG_BOOL bCommitBatch = bCommit;
+
+	if (!HANDLES_BATCHED(psBase))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: There is no handle batch"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+
+	}
+
+	if (psBase->ui32BatchHandAllocFailures != 0)
+	{
+		if (bCommit)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Attempting to commit batch with handle allocation failures."));
+		}
+		bCommitBatch = IMG_FALSE;
+	}
+
+	PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit);
+
+	ui32IndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
+	while(ui32IndexPlusOne != 0)
+	{
+		struct sHandle *psHandle = INDEX_TO_HANDLE_PTR(psBase, ui32IndexPlusOne - 1);
+		IMG_UINT32 ui32NextIndexPlusOne = psHandle->ui32NextIndexPlusOne;
+		PVR_ASSERT(BATCHED_HANDLE(psHandle));
+
+		psHandle->ui32NextIndexPlusOne = 0;
+
+		if (!bCommitBatch || BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+		{
+			PVRSRV_ERROR eError;
+
+
+			if (!BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+			{
+				SET_UNBATCHED_HANDLE(psHandle);
+			}
+
+			eError = FreeHandle(psBase, psHandle);
+			if (eError != PVRSRV_OK)
+			{
+				 PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Error freeing handle (%d)", eError));
+			}
+			PVR_ASSERT(eError == PVRSRV_OK);
+		}
+		else
+		{
+			SET_UNBATCHED_HANDLE(psHandle);
+		}
+
+		ui32IndexPlusOne = ui32NextIndexPlusOne;
+	}
+
+#ifdef DEBUG
+	if (psBase->ui32TotalHandCountPreBatch != psBase->ui32TotalHandCount)
+	{
+		IMG_UINT32 ui32Delta = psBase->ui32TotalHandCount - psBase->ui32TotalHandCountPreBatch;
+
+		PVR_ASSERT(psBase->ui32TotalHandCount > psBase->ui32TotalHandCountPreBatch);
+
+		PVR_DPF((PVR_DBG_WARNING, "PVRSRVHandleBatchCommitOrRelease: The batch size was too small.  Batch size was %u, but needs to be %u", psBase->ui32HandBatchSize,  psBase->ui32HandBatchSize + ui32Delta));
+
+	}
+#endif
+
+	psBase->ui32HandBatchSize = 0;
+	psBase->ui32FirstBatchIndexPlusOne = 0;
+	psBase->ui32TotalHandCountPreBatch = 0;
+	psBase->ui32BatchHandAllocFailures = 0;
+
+	if (psBase->ui32BatchHandAllocFailures != 0 && bCommit)
+	{
+		PVR_ASSERT(!bCommitBatch);
+
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+	return PVRSRVHandleBatchCommitOrRelease(psBase, IMG_TRUE);
+}
+
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+	(IMG_VOID) PVRSRVHandleBatchCommitOrRelease(psBase, IMG_FALSE);
+}
+
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
+{
+	if (HANDLES_BATCHED(psBase))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set whilst in batch mode"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+
+	if (ui32MaxHandle == 0 || ui32MaxHandle >= DEFAULT_MAX_HANDLE)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit must be between %u and %u, inclusive", 0, DEFAULT_MAX_HANDLE));
+
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+
+	if (psBase->ui32TotalHandCount != 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set becuase handles have already been allocated"));
+
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psBase->ui32MaxIndexPlusOne = ui32MaxHandle;
+
+	return PVRSRV_OK;
+}
+
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
+{
+	return psBase->ui32MaxIndexPlusOne;
+}
+
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
+{
+	if (psBase->bPurgingEnabled)
+	{
+		PVR_DPF((PVR_DBG_WARNING, "PVRSRVEnableHandlePurging: Purging already enabled"));
+		return PVRSRV_OK;
+	}
+
+
+	if (psBase->ui32TotalHandCount != 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVEnableHandlePurging: Handles have already been allocated"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psBase->bPurgingEnabled = IMG_TRUE;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+	IMG_UINT32 ui32Handle;
+	IMG_UINT32 ui32NewHandCount;
+
+	if (!psBase->bPurgingEnabled)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not enabled for this handle base"));
+		return PVRSRV_ERROR_NOT_SUPPORTED;
+	}
+
+	if (HANDLES_BATCHED(psBase))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not allowed whilst in batch mode"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	for (ui32Handle = psBase->ui32TotalHandCount; ui32Handle != 0; ui32Handle--)
+	{
+		struct sHandle *psHandle = HANDLE_TO_HANDLE_PTR(psBase, ui32Handle);
+		if (!HANDLE_STRUCT_IS_FREE(psHandle))
+		{
+			break;
+		}
+	}
+
+	ui32NewHandCount = ROUND_UP_TO_MULTIPLE(ui32Handle, HANDLE_BLOCK_SIZE);
+
+
+	if (ui32NewHandCount >= ui32Handle && ui32NewHandCount <= (psBase->ui32TotalHandCount/2))
+	{
+		IMG_UINT32 ui32Delta = psBase->ui32TotalHandCount - ui32NewHandCount;
+		PVRSRV_ERROR eError;
+
+
+
+		eError = ReallocHandleArray(psBase, ui32NewHandCount, psBase->ui32TotalHandCount);
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+
+
+		psBase->ui32TotalHandCount = ui32NewHandCount;
+		psBase->ui32FreeHandCount -= ui32Delta;
+		psBase->ui32FirstFreeIndex = 0;
+	}
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
+{
+	PVRSRV_HANDLE_BASE *psBase;
+	IMG_HANDLE hBlockAlloc;
+	PVRSRV_ERROR eError;
+
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+		sizeof(*psBase),
+		(IMG_PVOID *)&psBase,
+		&hBlockAlloc,
+		"Handle Base");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't allocate handle base (%d)", eError));
+		return eError;
+	}
+	OSMemSet(psBase, 0, sizeof(*psBase));
+
+
+	psBase->psHashTab = HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE, sizeof(HAND_KEY), HASH_Func_Default, HASH_Key_Comp_Default);
+	if (psBase->psHashTab == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't create data pointer hash table\n"));
+		goto failure;
+	}
+
+	psBase->hBaseBlockAlloc = hBlockAlloc;
+
+	psBase->ui32MaxIndexPlusOne = DEFAULT_MAX_INDEX_PLUS_ONE;
+
+	*ppsBase = psBase;
+
+	return PVRSRV_OK;
+failure:
+	(IMG_VOID)PVRSRVFreeHandleBase(psBase);
+	return PVRSRV_ERROR_GENERIC;
+}
+
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(psBase != gpsKernelHandleBase);
+
+	eError = FreeHandleBase(psBase);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeHandleBase: FreeHandleBase failed (%d)", eError));
+	}
+
+	return eError;
+}
+
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
+{
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(gpsKernelHandleBase == IMG_NULL);
+
+	eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVAllocHandleBase failed (%d)", eError));
+		goto error;
+	}
+
+	eError = PVRSRVEnableHandlePurging(gpsKernelHandleBase);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVEnableHandlePurging failed (%d)", eError));
+		goto error;
+	}
+
+	return PVRSRV_OK;
+error:
+	(IMG_VOID) PVRSRVHandleDeInit();
+	return eError;
+}
+
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if (gpsKernelHandleBase != IMG_NULL)
+	{
+		eError = FreeHandleBase(gpsKernelHandleBase);
+		if (eError == PVRSRV_OK)
+		{
+			gpsKernelHandleBase = IMG_NULL;
+		}
+		else
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleDeInit: FreeHandleBase failed (%d)", eError));
+		}
+	}
+
+	return eError;
+}
+#else
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/hash.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/hash.c
new file mode 100644
index 0000000..981702b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/hash.c
@@ -0,0 +1,459 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "pvr_debug.h"
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "hash.h"
+#include "osfunc.h"
+
+#define PRIVATE_MAX(a,b) ((a)>(b)?(a):(b))
+
+#define	KEY_TO_INDEX(pHash, key, uSize) \
+	((pHash)->pfnHashFunc((pHash)->uKeySize, key, uSize) % uSize)
+
+#define	KEY_COMPARE(pHash, pKey1, pKey2) \
+	((pHash)->pfnKeyComp((pHash)->uKeySize, pKey1, pKey2))
+
+struct _BUCKET_
+{
+
+	struct _BUCKET_ *pNext;
+
+
+	IMG_UINTPTR_T v;
+
+
+	IMG_UINTPTR_T k[];
+};
+typedef struct _BUCKET_ BUCKET;
+
+struct _HASH_TABLE_
+{
+
+	BUCKET **ppBucketTable;
+
+
+	IMG_UINT32 uSize;
+
+
+	IMG_UINT32 uCount;
+
+
+	IMG_UINT32 uMinimumSize;
+
+
+	IMG_UINT32 uKeySize;
+
+
+	HASH_FUNC *pfnHashFunc;
+
+
+	HASH_KEY_COMP *pfnKeyComp;
+};
+
+IMG_UINT32
+HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen)
+{
+	IMG_UINTPTR_T *p = (IMG_UINTPTR_T *)pKey;
+	IMG_UINT32 uKeyLen = uKeySize / sizeof(IMG_UINTPTR_T);
+	IMG_UINT32 ui;
+	IMG_UINT32 uHashKey = 0;
+
+	PVR_UNREFERENCED_PARAMETER(uHashTabLen);
+
+	PVR_ASSERT((uKeySize % sizeof(IMG_UINTPTR_T)) == 0);
+
+	for (ui = 0; ui < uKeyLen; ui++)
+	{
+		IMG_UINT32 uHashPart = (IMG_UINT32)*p++;
+
+		uHashPart += (uHashPart << 12);
+		uHashPart ^= (uHashPart >> 22);
+		uHashPart += (uHashPart << 4);
+		uHashPart ^= (uHashPart >> 9);
+		uHashPart += (uHashPart << 10);
+		uHashPart ^= (uHashPart >> 2);
+		uHashPart += (uHashPart << 7);
+		uHashPart ^= (uHashPart >> 12);
+
+		uHashKey += uHashPart;
+	}
+
+	return uHashKey;
+}
+
+IMG_BOOL
+HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2)
+{
+	IMG_UINTPTR_T *p1 = (IMG_UINTPTR_T *)pKey1;
+	IMG_UINTPTR_T *p2 = (IMG_UINTPTR_T *)pKey2;
+	IMG_UINT32 uKeyLen = uKeySize / sizeof(IMG_UINTPTR_T);
+	IMG_UINT32 ui;
+
+	PVR_ASSERT((uKeySize % sizeof(IMG_UINTPTR_T)) == 0);
+
+	for (ui = 0; ui < uKeyLen; ui++)
+	{
+		if (*p1++ != *p2++)
+			return IMG_FALSE;
+	}
+
+	return IMG_TRUE;
+}
+
+static PVRSRV_ERROR
+_ChainInsert (HASH_TABLE *pHash, BUCKET *pBucket, BUCKET **ppBucketTable, IMG_UINT32 uSize)
+{
+	IMG_UINT32 uIndex;
+
+	PVR_ASSERT (pBucket != IMG_NULL);
+	PVR_ASSERT (ppBucketTable != IMG_NULL);
+	PVR_ASSERT (uSize != 0);
+
+	if ((pBucket == IMG_NULL) || (ppBucketTable == IMG_NULL) || (uSize == 0))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "_ChainInsert: invalid parameter"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	uIndex = KEY_TO_INDEX(pHash, pBucket->k, uSize);
+	pBucket->pNext = ppBucketTable[uIndex];
+	ppBucketTable[uIndex] = pBucket;
+
+	return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+_Rehash (HASH_TABLE *pHash,
+	 BUCKET **ppOldTable, IMG_UINT32 uOldSize,
+         BUCKET **ppNewTable, IMG_UINT32 uNewSize)
+{
+	IMG_UINT32 uIndex;
+	for (uIndex=0; uIndex< uOldSize; uIndex++)
+    {
+		BUCKET *pBucket;
+		pBucket = ppOldTable[uIndex];
+		while (pBucket != IMG_NULL)
+		{
+			BUCKET *pNextBucket = pBucket->pNext;
+			if (_ChainInsert (pHash, pBucket, ppNewTable, uNewSize) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "_Rehash: call to _ChainInsert failed"));
+				return PVRSRV_ERROR_GENERIC;
+			}
+			pBucket = pNextBucket;
+		}
+    }
+	return PVRSRV_OK;
+}
+
+static IMG_BOOL
+_Resize (HASH_TABLE *pHash, IMG_UINT32 uNewSize)
+{
+	if (uNewSize != pHash->uSize)
+    {
+		BUCKET **ppNewTable;
+        IMG_UINT32 uIndex;
+
+		PVR_DPF ((PVR_DBG_MESSAGE,
+                  "HASH_Resize: oldsize=0x%x  newsize=0x%x  count=0x%x",
+				pHash->uSize, uNewSize, pHash->uCount));
+
+		OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+                      sizeof (BUCKET *) * uNewSize,
+                      (IMG_PVOID*)&ppNewTable, IMG_NULL,
+					  "Hash Table Buckets");
+		if (ppNewTable == IMG_NULL)
+            return IMG_FALSE;
+
+        for (uIndex=0; uIndex<uNewSize; uIndex++)
+            ppNewTable[uIndex] = IMG_NULL;
+
+        if (_Rehash (pHash, pHash->ppBucketTable, pHash->uSize, ppNewTable, uNewSize) != PVRSRV_OK)
+		{
+			return IMG_FALSE;
+		}
+
+        OSFreeMem (PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *)*pHash->uSize, pHash->ppBucketTable, IMG_NULL);
+
+        pHash->ppBucketTable = ppNewTable;
+        pHash->uSize = uNewSize;
+    }
+    return IMG_TRUE;
+}
+
+
+HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp)
+{
+	HASH_TABLE *pHash;
+	IMG_UINT32 uIndex;
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Create_Extended: InitialSize=0x%x", uInitialLen));
+
+	if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+					sizeof(HASH_TABLE),
+					(IMG_VOID **)&pHash, IMG_NULL,
+					"Hash Table") != PVRSRV_OK)
+	{
+		return IMG_NULL;
+	}
+
+	pHash->uCount = 0;
+	pHash->uSize = uInitialLen;
+	pHash->uMinimumSize = uInitialLen;
+	pHash->uKeySize = uKeySize;
+	pHash->pfnHashFunc = pfnHashFunc;
+	pHash->pfnKeyComp = pfnKeyComp;
+
+	OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+                  sizeof (BUCKET *) * pHash->uSize,
+                  (IMG_PVOID*)&pHash->ppBucketTable, IMG_NULL,
+				  "Hash Table Buckets");
+
+	if (pHash->ppBucketTable == IMG_NULL)
+    {
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash, IMG_NULL);
+
+		return IMG_NULL;
+    }
+
+	for (uIndex=0; uIndex<pHash->uSize; uIndex++)
+		pHash->ppBucketTable[uIndex] = IMG_NULL;
+	return pHash;
+}
+
+HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen)
+{
+	return HASH_Create_Extended(uInitialLen, sizeof(IMG_UINTPTR_T),
+		&HASH_Func_Default, &HASH_Key_Comp_Default);
+}
+
+IMG_VOID
+HASH_Delete (HASH_TABLE *pHash)
+{
+	if (pHash != IMG_NULL)
+    {
+		PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Delete"));
+
+		PVR_ASSERT (pHash->uCount==0);
+		if(pHash->uCount != 0)
+		{
+			PVR_DPF ((PVR_DBG_ERROR, "HASH_Delete: leak detected in hash table!"));
+			PVR_DPF ((PVR_DBG_ERROR, "Likely Cause: client drivers not freeing alocations before destroying devmemcontext"));
+		}
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *)*pHash->uSize, pHash->ppBucketTable, IMG_NULL);
+		pHash->ppBucketTable = IMG_NULL;
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash, IMG_NULL);
+
+    }
+}
+
+IMG_BOOL
+HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v)
+{
+	BUCKET *pBucket;
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+              "HASH_Insert_Extended: Hash=%08X, pKey=%08X, v=0x%x", pHash, pKey, v));
+
+	PVR_ASSERT (pHash != IMG_NULL);
+
+	if (pHash == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "HASH_Insert_Extended: invalid parameter"));
+		return IMG_FALSE;
+	}
+
+	if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+					sizeof(BUCKET) + pHash->uKeySize,
+					(IMG_VOID **)&pBucket, IMG_NULL,
+					"Hash Table entry") != PVRSRV_OK)
+	{
+		return IMG_FALSE;
+	}
+
+	pBucket->v = v;
+
+	OSMemCopy(pBucket->k, pKey, pHash->uKeySize);
+	if (_ChainInsert (pHash, pBucket, pHash->ppBucketTable, pHash->uSize) != PVRSRV_OK)
+	{
+		return IMG_FALSE;
+	}
+
+	pHash->uCount++;
+
+
+	if (pHash->uCount << 1 > pHash->uSize)
+    {
+
+
+        _Resize (pHash, pHash->uSize << 1);
+    }
+
+
+	return IMG_TRUE;
+}
+
+IMG_BOOL
+HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v)
+{
+	PVR_DPF ((PVR_DBG_MESSAGE,
+              "HASH_Insert: Hash=%08X, k=0x%x, v=0x%x", pHash, k, v));
+
+	return HASH_Insert_Extended(pHash, &k, v);
+}
+
+IMG_UINTPTR_T
+HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey)
+{
+	BUCKET **ppBucket;
+	IMG_UINT32 uIndex;
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Remove_Extended: Hash=%08X, pKey=%08X", pHash, pKey));
+
+	PVR_ASSERT (pHash != IMG_NULL);
+
+	if (pHash == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "HASH_Remove_Extended: Null hash table"));
+		return 0;
+	}
+
+	uIndex = KEY_TO_INDEX(pHash, pKey, pHash->uSize);
+
+	for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
+	{
+
+		if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
+		{
+			BUCKET *pBucket = *ppBucket;
+			IMG_UINTPTR_T v = pBucket->v;
+			(*ppBucket) = pBucket->pNext;
+
+			OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET) + pHash->uKeySize, pBucket, IMG_NULL);
+
+
+			pHash->uCount--;
+
+
+			if (pHash->uSize > (pHash->uCount << 2) &&
+                pHash->uSize > pHash->uMinimumSize)
+            {
+
+
+				_Resize (pHash,
+                         PRIVATE_MAX (pHash->uSize >> 1,
+                                      pHash->uMinimumSize));
+            }
+
+			PVR_DPF ((PVR_DBG_MESSAGE,
+                      "HASH_Remove_Extended: Hash=%08X, pKey=%08X = 0x%x",
+                      pHash, pKey, v));
+			return v;
+		}
+	}
+	PVR_DPF ((PVR_DBG_MESSAGE,
+              "HASH_Remove_Extended: Hash=%08X, pKey=%08X = 0x0 !!!!", pHash, pKey));
+	return 0;
+}
+
+IMG_UINTPTR_T
+HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k)
+{
+	PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Remove: Hash=%08X, k=0x%x", pHash, k));
+
+	return HASH_Remove_Extended(pHash, &k);
+}
+
+IMG_UINTPTR_T
+HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey)
+{
+	BUCKET **ppBucket;
+	IMG_UINT32 uIndex;
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Retrieve_Extended: Hash=%08X, pKey=%08X", pHash,pKey));
+
+	PVR_ASSERT (pHash != IMG_NULL);
+
+	if (pHash == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "HASH_Retrieve_Extended: Null hash table"));
+		return 0;
+	}
+
+	uIndex = KEY_TO_INDEX(pHash, pKey, pHash->uSize);
+
+	for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
+	{
+
+		if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
+		{
+			BUCKET *pBucket = *ppBucket;
+			IMG_UINTPTR_T v = pBucket->v;
+
+			PVR_DPF ((PVR_DBG_MESSAGE,
+                      "HASH_Retrieve: Hash=%08X, pKey=%08X = 0x%x",
+                      pHash, pKey, v));
+			return v;
+		}
+	}
+	PVR_DPF ((PVR_DBG_MESSAGE,
+              "HASH_Retrieve: Hash=%08X, pKey=%08X = 0x0 !!!!", pHash, pKey));
+	return 0;
+}
+
+IMG_UINTPTR_T
+HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k)
+{
+	PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Retrieve: Hash=%08X, k=0x%x", pHash,k));
+	return HASH_Retrieve_Extended(pHash, &k);
+}
+
+#ifdef HASH_TRACE
+IMG_VOID
+HASH_Dump (HASH_TABLE *pHash)
+{
+	IMG_UINT32 uIndex;
+	IMG_UINT32 uMaxLength=0;
+	IMG_UINT32 uEmptyCount=0;
+
+	PVR_ASSERT (pHash != IMG_NULL);
+	for (uIndex=0; uIndex<pHash->uSize; uIndex++)
+	{
+		BUCKET *pBucket;
+		IMG_UINT32 uLength = 0;
+		if (pHash->ppBucketTable[uIndex] == IMG_NULL)
+			uEmptyCount++;
+		for (pBucket=pHash->ppBucketTable[uIndex];
+		pBucket != IMG_NULL;
+		pBucket = pBucket->pNext)
+				uLength++;
+		uMaxLength = PRIVATE_MAX (uMaxLength, uLength);
+	}
+
+	PVR_TRACE(("hash table: uMinimumSize=%d  size=%d  count=%d",
+			pHash->uMinimumSize, pHash->uSize, pHash->uCount));
+	PVR_TRACE(("  empty=%d  max=%d", uEmptyCount, uMaxLength));
+}
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/lists.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/lists.c
new file mode 100644
index 0000000..1d7602a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/lists.c
@@ -0,0 +1,95 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "lists.h"
+#include "services_headers.h"
+
+IMPLEMENT_LIST_ANY_VA(BM_HEAP)
+IMPLEMENT_LIST_ANY_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_ANY_VA_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH_VA(BM_HEAP)
+IMPLEMENT_LIST_REMOVE(BM_HEAP)
+IMPLEMENT_LIST_INSERT(BM_HEAP)
+
+IMPLEMENT_LIST_ANY_VA(BM_CONTEXT)
+IMPLEMENT_LIST_ANY_VA_2(BM_CONTEXT, IMG_HANDLE, IMG_NULL)
+IMPLEMENT_LIST_ANY_VA_2(BM_CONTEXT, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH(BM_CONTEXT)
+IMPLEMENT_LIST_REMOVE(BM_CONTEXT)
+IMPLEMENT_LIST_INSERT(BM_CONTEXT)
+
+IMPLEMENT_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_ANY_VA(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_INSERT(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_REMOVE(PVRSRV_DEVICE_NODE)
+
+IMPLEMENT_LIST_ANY_VA(PVRSRV_POWER_DEV)
+IMPLEMENT_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_INSERT(PVRSRV_POWER_DEV)
+IMPLEMENT_LIST_REMOVE(PVRSRV_POWER_DEV)
+
+
+IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va)
+{
+	IMG_UINT32 ui32DevIndex;
+	IMG_BOOL bIgnoreClass;
+	PVRSRV_DEVICE_CLASS eDevClass;
+
+	ui32DevIndex = va_arg(va, IMG_UINT32);
+	bIgnoreClass = va_arg(va, IMG_BOOL);
+	if (!bIgnoreClass)
+	{
+		eDevClass = va_arg(va, PVRSRV_DEVICE_CLASS);
+	}
+	else
+	{
+
+
+		eDevClass = PVRSRV_DEVICE_CLASS_FORCE_I32;
+	}
+
+	if ((bIgnoreClass || psDeviceNode->sDevId.eDeviceClass == eDevClass) &&
+		psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex)
+	{
+		return psDeviceNode;
+	}
+	return IMG_NULL;
+}
+
+IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va)
+{
+	IMG_UINT32 ui32DeviceIndex;
+
+	ui32DeviceIndex = va_arg(va, IMG_UINT32);
+
+	if (psPowerDev->ui32DeviceIndex == ui32DeviceIndex)
+	{
+		return psPowerDev;
+	}
+	else
+	{
+		return IMG_NULL;
+	}
+}
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/mem.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/mem.c
new file mode 100644
index 0000000..0dd99db
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/mem.c
@@ -0,0 +1,147 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "pvr_bridge_km.h"
+
+
+static PVRSRV_ERROR
+FreeSharedSysMemCallBack(IMG_PVOID	pvParam,
+						 IMG_UINT32	ui32Param)
+{
+	PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = pvParam;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+	OSFreePages(psKernelMemInfo->ui32Flags,
+				psKernelMemInfo->ui32AllocSize,
+				psKernelMemInfo->pvLinAddrKM,
+				psKernelMemInfo->sMemBlk.hOSMemHandle);
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+			  sizeof(PVRSRV_KERNEL_MEM_INFO),
+			  psKernelMemInfo,
+			  IMG_NULL);
+
+
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+							 IMG_UINT32					ui32Flags,
+							 IMG_SIZE_T 				ui32Size,
+							 PVRSRV_KERNEL_MEM_INFO 	**ppsKernelMemInfo)
+{
+	PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_KERNEL_MEM_INFO),
+				  (IMG_VOID **)&psKernelMemInfo, IMG_NULL,
+				  "Kernel Memory Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for meminfo"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	OSMemSet(psKernelMemInfo, 0, sizeof(*psKernelMemInfo));
+
+	ui32Flags &= ~PVRSRV_HAP_MAPTYPE_MASK;
+	ui32Flags |= PVRSRV_HAP_MULTI_PROCESS;
+	psKernelMemInfo->ui32Flags = ui32Flags;
+	psKernelMemInfo->ui32AllocSize = ui32Size;
+
+	if(OSAllocPages(psKernelMemInfo->ui32Flags,
+					psKernelMemInfo->ui32AllocSize,
+					HOST_PAGESIZE(),
+					&psKernelMemInfo->pvLinAddrKM,
+					&psKernelMemInfo->sMemBlk.hOSMemHandle)
+		!= PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for block"));
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_KERNEL_MEM_INFO),
+				  psKernelMemInfo,
+				  0);
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+
+	psKernelMemInfo->sMemBlk.hResItem =
+				ResManRegisterRes(psPerProc->hResManContext,
+								  RESMAN_TYPE_SHARED_MEM_INFO,
+								  psKernelMemInfo,
+								  0,
+								  FreeSharedSysMemCallBack);
+
+	*ppsKernelMemInfo = psKernelMemInfo;
+
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVFreeSharedSysMemoryKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	PVRSRV_ERROR eError;
+
+	if(psKernelMemInfo->sMemBlk.hResItem)
+	{
+		eError = ResManFreeResByPtr(psKernelMemInfo->sMemBlk.hResItem);
+	}
+	else
+	{
+		eError = FreeSharedSysMemCallBack(psKernelMemInfo, 0);
+	}
+
+	return eError;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVDissociateMemFromResmanKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if(!psKernelMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if(psKernelMemInfo->sMemBlk.hResItem)
+	{
+		eError = ResManDissociateRes(psKernelMemInfo->sMemBlk.hResItem, IMG_NULL);
+
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVDissociateMemFromResmanKM: ResManDissociateRes failed"));
+			PVR_DBG_BREAK;
+			return eError;
+		}
+
+		psKernelMemInfo->sMemBlk.hResItem = IMG_NULL;
+	}
+
+	return eError;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/mem_debug.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/mem_debug.c
new file mode 100644
index 0000000..e9ae968
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/mem_debug.c
@@ -0,0 +1,246 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef MEM_DEBUG_C
+#define MEM_DEBUG_C
+
+#if defined(PVRSRV_DEBUG_OS_MEMORY)
+
+#include "img_types.h"
+#include "services_headers.h"
+
+#if defined (__cplusplus)
+extern "C"
+{
+#endif
+
+#define STOP_ON_ERROR 0
+
+
+
+
+
+
+
+
+
+	IMG_BOOL MemCheck(const IMG_PVOID pvAddr, const IMG_UINT8 ui8Pattern, IMG_SIZE_T uSize)
+	{
+		IMG_UINT8 *pui8Addr;
+		for (pui8Addr = (IMG_UINT8*)pvAddr; uSize > 0; uSize--, pui8Addr++)
+		{
+			if (*pui8Addr != ui8Pattern)
+			{
+				return IMG_FALSE;
+			}
+		}
+		return IMG_TRUE;
+	}
+
+
+
+	IMG_VOID OSCheckMemDebug(IMG_PVOID pvCpuVAddr, IMG_SIZE_T uSize, const IMG_CHAR *pszFileName, const IMG_UINT32 uLine)
+	{
+		OSMEM_DEBUG_INFO const *psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32)pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
+
+
+		if (pvCpuVAddr == IMG_NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : null pointer"
+					 " - referenced %s:%d - allocated %s:%d",
+					 pvCpuVAddr,
+					 pszFileName, uLine,
+					 psInfo->sFileName, psInfo->uLineNo));
+			while (STOP_ON_ERROR);
+		}
+
+
+		if (((IMG_UINT32)pvCpuVAddr&3) != 0)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : invalid alignment"
+					 " - referenced %s:%d - allocated %s:%d",
+					 pvCpuVAddr,
+					 pszFileName, uLine,
+					 psInfo->sFileName, psInfo->uLineNo));
+			while (STOP_ON_ERROR);
+		}
+
+
+		if (!MemCheck((IMG_PVOID)psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore)))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : guard region before overwritten"
+					 " - referenced %s:%d - allocated %s:%d",
+					 pvCpuVAddr,
+					 pszFileName, uLine,
+					 psInfo->sFileName, psInfo->uLineNo));
+			while (STOP_ON_ERROR);
+		}
+
+
+		if (uSize != psInfo->uSize)
+		{
+			PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : supplied size was different to stored size (0x%X != 0x%X)"
+					 " - referenced %s:%d - allocated %s:%d",
+					 pvCpuVAddr, uSize, psInfo->uSize,
+					 pszFileName, uLine,
+					 psInfo->sFileName, psInfo->uLineNo));
+			while (STOP_ON_ERROR);
+		}
+
+
+		if ((0x01234567 ^ psInfo->uSizeParityCheck) != psInfo->uSize)
+		{
+			PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : stored size parity error (0x%X != 0x%X)"
+					 " - referenced %s:%d - allocated %s:%d",
+					 pvCpuVAddr, psInfo->uSize, 0x01234567 ^ psInfo->uSizeParityCheck,
+					 pszFileName, uLine,
+					 psInfo->sFileName, psInfo->uLineNo));
+			while (STOP_ON_ERROR);
+		}
+		else
+		{
+
+			uSize = psInfo->uSize;
+		}
+
+
+		if (uSize)
+		{
+			if (!MemCheck((IMG_VOID*)((IMG_UINT32)pvCpuVAddr + uSize), 0xB2, TEST_BUFFER_PADDING_AFTER))
+			{
+				PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : guard region after overwritten"
+						 " - referenced from %s:%d - allocated from %s:%d",
+						 pvCpuVAddr,
+						 pszFileName, uLine,
+						 psInfo->sFileName, psInfo->uLineNo));
+			}
+		}
+
+
+		if (psInfo->eValid != isAllocated)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : not allocated (freed? %d)"
+					 " - referenced %s:%d - freed %s:%d",
+					 pvCpuVAddr, psInfo->eValid == isFree,
+					 pszFileName, uLine,
+					 psInfo->sFileName, psInfo->uLineNo));
+			while (STOP_ON_ERROR);
+		}
+	}
+
+	IMG_VOID debug_strcpy(IMG_CHAR *pDest, const IMG_CHAR *pSrc)
+	{
+		IMG_SIZE_T i = 0;
+
+		for (; i < 128; i++)
+		{
+			*pDest = *pSrc;
+			if (*pSrc == '\0') break;
+			pDest++;
+			pSrc++;
+		}
+	}
+
+	PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+										  IMG_UINT32 ui32Size,
+										  IMG_PVOID *ppvCpuVAddr,
+										  IMG_HANDLE *phBlockAlloc,
+										  IMG_CHAR *pszFilename,
+										  IMG_UINT32 ui32Line)
+	{
+		OSMEM_DEBUG_INFO *psInfo;
+
+		PVRSRV_ERROR eError;
+
+		eError = OSAllocMem_Debug_Linux_Memory_Allocations(ui32Flags,
+				 ui32Size + TEST_BUFFER_PADDING,
+				 ppvCpuVAddr,
+				 phBlockAlloc,
+				 pszFilename,
+				 ui32Line);
+
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+
+
+		OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + TEST_BUFFER_PADDING_STATUS, 0xBB, ui32Size);
+		OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + ui32Size + TEST_BUFFER_PADDING_STATUS, 0xB2, TEST_BUFFER_PADDING_AFTER);
+
+
+		psInfo = (OSMEM_DEBUG_INFO *)(*ppvCpuVAddr);
+
+		OSMemSet(psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore));
+		debug_strcpy(psInfo->sFileName, pszFilename);
+		psInfo->uLineNo = ui32Line;
+		psInfo->eValid = isAllocated;
+		psInfo->uSize = ui32Size;
+		psInfo->uSizeParityCheck = 0x01234567 ^ ui32Size;
+
+
+		*ppvCpuVAddr = (IMG_PVOID) ((IMG_UINT32)*ppvCpuVAddr)+TEST_BUFFER_PADDING_STATUS;
+
+#ifdef PVRSRV_LOG_MEMORY_ALLOCS
+
+		PVR_TRACE(("Allocated pointer (after debug info): 0x%X from %s:%d", *ppvCpuVAddr, pszFilename, ui32Line));
+#endif
+
+		return PVRSRV_OK;
+	}
+
+	PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+										 IMG_UINT32 ui32Size,
+										 IMG_PVOID pvCpuVAddr,
+										 IMG_HANDLE hBlockAlloc,
+										 IMG_CHAR *pszFilename,
+										 IMG_UINT32 ui32Line)
+	{
+		OSMEM_DEBUG_INFO *psInfo;
+
+
+		OSCheckMemDebug(pvCpuVAddr, ui32Size, pszFilename, ui32Line);
+
+
+		OSMemSet(pvCpuVAddr, 0xBF, ui32Size + TEST_BUFFER_PADDING_AFTER);
+
+
+		psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32) pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
+
+
+		psInfo->uSize = 0;
+		psInfo->uSizeParityCheck = 0;
+		psInfo->eValid = isFree;
+		psInfo->uLineNo = ui32Line;
+		debug_strcpy(psInfo->sFileName, pszFilename);
+
+		return OSFreeMem_Debug_Linux_Memory_Allocations(ui32Flags, ui32Size + TEST_BUFFER_PADDING, psInfo, hBlockAlloc, pszFilename, ui32Line);
+	}
+
+#if defined (__cplusplus)
+
+}
+#endif
+
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/metrics.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/metrics.c
new file mode 100644
index 0000000..c1df322
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/metrics.c
@@ -0,0 +1,156 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "metrics.h"
+
+#if defined(SUPPORT_VGX)
+#include "vgxapi_km.h"
+#endif
+
+#if defined(SUPPORT_SGX)
+#include "sgxapi_km.h"
+#endif
+
+#if defined(DEBUG) || defined(TIMING)
+
+static volatile IMG_UINT32 *pui32TimerRegister = 0;
+
+#define PVRSRV_TIMER_TOTAL_IN_TICKS(X)	asTimers[X].ui32Total
+#define PVRSRV_TIMER_TOTAL_IN_MS(X)		((1000*asTimers[X].ui32Total)/ui32TicksPerMS)
+#define PVRSRV_TIMER_COUNT(X)			asTimers[X].ui32Count
+
+
+Temporal_Data asTimers[PVRSRV_NUM_TIMERS];
+
+
+IMG_UINT32 PVRSRVTimeNow(IMG_VOID)
+{
+	if (!pui32TimerRegister)
+	{
+		static IMG_BOOL bFirstTime = IMG_TRUE;
+
+		if (bFirstTime)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVTimeNow: No timer register set up"));
+
+			bFirstTime = IMG_FALSE;
+		}
+
+		return 0;
+	}
+
+#if defined(__sh__)
+
+	return (0xffffffff-*pui32TimerRegister);
+
+#else
+
+	return 0;
+
+#endif
+}
+
+
+static IMG_UINT32 PVRSRVGetCPUFreq(IMG_VOID)
+{
+	IMG_UINT32 ui32Time1, ui32Time2;
+
+	ui32Time1 = PVRSRVTimeNow();
+
+	OSWaitus(1000000);
+
+	ui32Time2 = PVRSRVTimeNow();
+
+	PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetCPUFreq: timer frequency = %d Hz", ui32Time2 - ui32Time1));
+
+	return (ui32Time2 - ui32Time1);
+}
+
+
+IMG_VOID PVRSRVSetupMetricTimers(IMG_VOID *pvDevInfo)
+{
+	IMG_UINT32 ui32Loop;
+
+	PVR_UNREFERENCED_PARAMETER(pvDevInfo);
+
+	for(ui32Loop=0; ui32Loop < (PVRSRV_NUM_TIMERS); ui32Loop++)
+	{
+		asTimers[ui32Loop].ui32Total = 0;
+		asTimers[ui32Loop].ui32Count = 0;
+	}
+
+
+	#if defined(__sh__)
+
+
+
+
+
+		*TCR_2 = TIMER_DIVISOR;
+
+
+		*TCOR_2 = *TCNT_2 = (IMG_UINT)0xffffffff;
+
+
+		*TST_REG |= (IMG_UINT8)0x04;
+
+		pui32TimerRegister = (IMG_UINT32 *)TCNT_2;
+
+	#else
+
+		pui32TimerRegister = 0;
+
+	#endif
+
+}
+
+
+IMG_VOID PVRSRVOutputMetricTotals(IMG_VOID)
+{
+	IMG_UINT32 ui32TicksPerMS, ui32Loop;
+
+	ui32TicksPerMS = PVRSRVGetCPUFreq();
+
+	if (!ui32TicksPerMS)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVOutputMetricTotals: Failed to get CPU Freq"));
+		return;
+	}
+
+	for(ui32Loop=0; ui32Loop < (PVRSRV_NUM_TIMERS); ui32Loop++)
+	{
+		if (asTimers[ui32Loop].ui32Count & 0x80000000L)
+		{
+			PVR_DPF((PVR_DBG_WARNING,"PVRSRVOutputMetricTotals: Timer %u is still ON", ui32Loop));
+		}
+	}
+#if 0
+
+	PVR_DPF((PVR_DBG_ERROR," Timer(%u): Total = %u",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_TOTAL_IN_TICKS(PVRSRV_TIMER_EXAMPLE_1)));
+	PVR_DPF((PVR_DBG_ERROR," Timer(%u): Time = %ums",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_TOTAL_IN_MS(PVRSRV_TIMER_EXAMPLE_1)));
+	PVR_DPF((PVR_DBG_ERROR," Timer(%u): Count = %u",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_COUNT(PVRSRV_TIMER_EXAMPLE_1)));
+#endif
+}
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/pdump_common.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/pdump_common.c
new file mode 100644
index 0000000..518a583
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/pdump_common.c
@@ -0,0 +1,1723 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if defined(PDUMP)
+
+#include <stdarg.h>
+
+#include "services_headers.h"
+#if defined(SUPPORT_SGX)
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#endif
+#include "pdump_km.h"
+
+#if !defined(PDUMP_TEMP_BUFFER_SIZE)
+#define PDUMP_TEMP_BUFFER_SIZE (64 * 1024L)
+#endif
+
+#if 1
+#define PDUMP_DBG(a)   PDumpOSDebugPrintf a
+#else
+#define PDUMP_DBG(a)
+#endif
+
+#define PDUMP_DATAMASTER_PIXEL		(1)
+#define PDUMP_DATAMASTER_EDM		(3)
+
+#define	MIN(x, y) (((x) < (y)) ? (x) : (y))
+#define	PTR_PLUS(t, p, x) ((t *)(((IMG_CHAR *)(p)) + (x)))
+#define	VPTR_PLUS(p, x) PTR_PLUS(IMG_VOID, p, x)
+#define	VPTR_INC(p, x) (p = VPTR_PLUS(p, x))
+#define MAX_PDUMP_MMU_CONTEXTS	(32)
+static IMG_VOID *gpvTempBuffer = IMG_NULL;
+static IMG_HANDLE ghTempBufferBlockAlloc;
+static IMG_UINT16 gui16MMUContextUsage = 0;
+
+
+
+static IMG_VOID *GetTempBuffer(IMG_VOID)
+{
+
+	if (gpvTempBuffer == IMG_NULL)
+	{
+		PVRSRV_ERROR eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					  PDUMP_TEMP_BUFFER_SIZE,
+					  &gpvTempBuffer,
+					  &ghTempBufferBlockAlloc,
+					  "PDUMP Temporary Buffer");
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "GetTempBuffer: OSAllocMem failed: %d", eError));
+		}
+	}
+
+	return gpvTempBuffer;
+}
+
+static IMG_VOID FreeTempBuffer(IMG_VOID)
+{
+
+	if (gpvTempBuffer != IMG_NULL)
+	{
+		PVRSRV_ERROR eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+					  PDUMP_TEMP_BUFFER_SIZE,
+					  gpvTempBuffer,
+					  ghTempBufferBlockAlloc);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "FreeTempBuffer: OSFreeMem failed: %d", eError));
+		}
+		else
+		{
+			gpvTempBuffer = IMG_NULL;
+		}
+	}
+}
+
+IMG_VOID PDumpInitCommon(IMG_VOID)
+{
+
+	(IMG_VOID) GetTempBuffer();
+
+
+	PDumpInit();
+}
+
+IMG_VOID PDumpDeInitCommon(IMG_VOID)
+{
+
+	FreeTempBuffer();
+
+
+	PDumpDeInit();
+}
+
+#if defined(SGX_SUPPORT_COMMON_PDUMP)
+
+IMG_BOOL PDumpIsSuspended(IMG_VOID)
+{
+	return PDumpOSIsSuspended();
+}
+
+PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_UINT32 ui32Reg, IMG_UINT32 ui32Data, IMG_UINT32 ui32Flags)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING()
+	PDUMP_DBG(("PDumpRegWithFlagsKM"));
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "WRW :SGXREG:0x%8.8lX 0x%8.8lX\r\n", ui32Reg, ui32Data);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpRegKM(IMG_UINT32 ui32Reg,IMG_UINT32 ui32Data)
+{
+	return PDumpRegWithFlagsKM(ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue, IMG_UINT32 ui32Mask, IMG_UINT32 ui32Flags)
+{
+
+	#define POLL_DELAY			1000UL
+	#define POLL_COUNT_LONG		(2000000000UL / POLL_DELAY)
+	#define POLL_COUNT_SHORT	(1000000UL / POLL_DELAY)
+
+	PVRSRV_ERROR eErr;
+	IMG_UINT32	ui32PollCount;
+
+	PDUMP_GET_SCRIPT_STRING();
+	PDUMP_DBG(("PDumpRegPolWithFlagsKM"));
+
+	if (((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+		(ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_TA_FINISHED_MASK) != 0) ||
+	    ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+		(ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK) != 0) ||
+	    ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+		(ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK) != 0))
+	{
+		ui32PollCount = POLL_COUNT_LONG;
+	}
+	else
+	{
+		ui32PollCount = POLL_COUNT_SHORT;
+	}
+
+
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "POL :SGXREG:0x%8.8lX 0x%8.8lX 0x%8.8lX %d %lu %d\r\n",
+			ui32RegAddr, ui32RegValue, ui32Mask, 0, ui32PollCount, POLL_DELAY);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpRegPolKM(IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue, IMG_UINT32 ui32Mask)
+{
+	return PDumpRegPolWithFlagsKM(ui32RegAddr, ui32RegValue, ui32Mask, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpMallocPages (PVRSRV_DEVICE_TYPE eDeviceType,
+                           IMG_UINT32         ui32DevVAddr,
+                           IMG_CPU_VIRTADDR   pvLinAddr,
+                           IMG_HANDLE         hOSMemHandle,
+                           IMG_UINT32         ui32NumBytes,
+                           IMG_UINT32         ui32PageSize,
+                           IMG_HANDLE         hUniqueTag)
+{
+	PVRSRV_ERROR eErr;
+	IMG_PUINT8		pui8LinAddr;
+    IMG_UINT32      ui32Offset;
+	IMG_UINT32		ui32NumPages;
+	IMG_DEV_PHYADDR	sDevPAddr;
+	IMG_UINT32		ui32Page;
+
+	PDUMP_GET_SCRIPT_STRING();
+
+#if defined(LINUX)
+	PVR_ASSERT(hOSMemHandle);
+#else
+
+	PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+	PVR_ASSERT(((IMG_UINT32) pvLinAddr & (SGX_MMU_PAGE_MASK)) == 0);
+#endif
+
+	PVR_ASSERT(((IMG_UINT32) ui32DevVAddr & (SGX_MMU_PAGE_MASK)) == 0);
+	PVR_ASSERT(((IMG_UINT32) ui32NumBytes & (SGX_MMU_PAGE_MASK)) == 0);
+
+
+
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- MALLOC :SGXMEM:VA_%8.8lX 0x%8.8lX %lu\r\n",
+			ui32DevVAddr, ui32NumBytes, ui32PageSize);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+
+
+	pui8LinAddr = (IMG_PUINT8) pvLinAddr;
+	ui32Offset = 0;
+	ui32NumPages = ui32NumBytes / ui32PageSize;
+	while (ui32NumPages)
+	{
+		ui32NumPages--;
+
+
+		PDumpOSCPUVAddrToDevPAddr(eDeviceType,
+				hOSMemHandle,
+				ui32Offset,
+				pui8LinAddr,
+				ui32PageSize,
+				&sDevPAddr);
+		ui32Page = sDevPAddr.uiAddr / ui32PageSize;
+
+		pui8LinAddr	+= ui32PageSize;
+		ui32Offset += ui32PageSize;
+
+		eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC :SGXMEM:PA_%8.8lX%8.8lX %lu %lu 0x%8.8lX\r\n",
+												(IMG_UINT32) hUniqueTag,
+												ui32Page * ui32PageSize,
+												ui32PageSize,
+												ui32PageSize,
+												ui32Page * ui32PageSize);
+		if(eErr != PVRSRV_OK)
+		{
+			return eErr;
+		}
+		PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+	}
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMallocPageTable (PVRSRV_DEVICE_TYPE eDeviceType,
+                               IMG_CPU_VIRTADDR   pvLinAddr,
+								IMG_UINT32        ui32PTSize,
+                               IMG_HANDLE         hUniqueTag)
+{
+	PVRSRV_ERROR eErr;
+	IMG_DEV_PHYADDR	sDevPAddr;
+	IMG_UINT32		ui32Page;
+
+	PDUMP_GET_SCRIPT_STRING();
+
+	PVR_ASSERT(((IMG_UINT32) pvLinAddr & (ui32PTSize - 1)) == 0);
+
+
+
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- MALLOC :SGXMEM:PAGE_TABLE 0x%8.8lX %lu\r\n", ui32PTSize, SGX_MMU_PAGE_SIZE);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	{
+
+
+		PDumpOSCPUVAddrToDevPAddr(eDeviceType,
+				IMG_NULL,
+				0,
+				(IMG_PUINT8) pvLinAddr,
+				SGX_MMU_PAGE_SIZE,
+				&sDevPAddr);
+		ui32Page = sDevPAddr.uiAddr >> SGX_MMU_PAGE_SHIFT;
+
+		eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC :SGXMEM:PA_%8.8lX%8.8lX 0x%lX %lu 0x%8.8lX\r\n",
+												(IMG_UINT32) hUniqueTag,
+												ui32Page * SGX_MMU_PAGE_SIZE,
+												SGX_MMU_PAGE_SIZE,
+												SGX_MMU_PAGE_SIZE,
+												ui32Page * SGX_MMU_PAGE_SIZE);
+		if(eErr != PVRSRV_OK)
+		{
+			return eErr;
+		}
+		PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+	}
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpFreePages	(BM_HEAP 			*psBMHeap,
+                         IMG_DEV_VIRTADDR  sDevVAddr,
+                         IMG_UINT32        ui32NumBytes,
+                         IMG_UINT32        ui32PageSize,
+                         IMG_HANDLE        hUniqueTag,
+						 IMG_BOOL		   bInterleaved)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32 ui32NumPages, ui32PageCounter;
+	IMG_DEV_PHYADDR	sDevPAddr;
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+	PDUMP_GET_SCRIPT_STRING();
+
+	PVR_ASSERT(((IMG_UINT32) sDevVAddr.uiAddr & (ui32PageSize - 1)) == 0);
+	PVR_ASSERT(((IMG_UINT32) ui32NumBytes & (ui32PageSize - 1)) == 0);
+
+
+
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :SGXMEM:VA_%8.8lX\r\n", sDevVAddr.uiAddr);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+
+
+	ui32NumPages = ui32NumBytes / ui32PageSize;
+	psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+	for (ui32PageCounter = 0; ui32PageCounter < ui32NumPages; ui32PageCounter++)
+	{
+		if (!bInterleaved || (ui32PageCounter % 2) == 0)
+		{
+			sDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(psBMHeap->pMMUHeap, sDevVAddr);
+			{
+				eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE :SGXMEM:PA_%8.8lX%8.8lX\r\n", (IMG_UINT32) hUniqueTag, sDevPAddr.uiAddr);
+				if(eErr != PVRSRV_OK)
+				{
+					return eErr;
+				}
+				PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+			}
+		}
+		else
+		{
+
+		}
+
+		sDevVAddr.uiAddr += ui32PageSize;
+	}
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpFreePageTable	(PVRSRV_DEVICE_TYPE eDeviceType,
+							 IMG_CPU_VIRTADDR   pvLinAddr,
+							 IMG_UINT32         ui32PTSize,
+							 IMG_HANDLE         hUniqueTag)
+{
+	PVRSRV_ERROR eErr;
+	IMG_DEV_PHYADDR	sDevPAddr;
+	IMG_UINT32		ui32Page;
+
+	PDUMP_GET_SCRIPT_STRING();
+
+	PVR_UNREFERENCED_PARAMETER(ui32PTSize);
+
+
+	PVR_ASSERT(((IMG_UINT32) pvLinAddr & (ui32PTSize-1UL)) == 0);
+
+
+
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :SGXMEM:PAGE_TABLE\r\n");
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+
+
+
+
+
+
+
+
+
+
+
+	{
+		PDumpOSCPUVAddrToDevPAddr(eDeviceType,
+				IMG_NULL,
+				0,
+				(IMG_PUINT8) pvLinAddr,
+				SGX_MMU_PAGE_SIZE,
+				&sDevPAddr);
+		ui32Page = sDevPAddr.uiAddr >> SGX_MMU_PAGE_SHIFT;
+
+		{
+			eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE :SGXMEM:PA_%8.8lX%8.8lX\r\n", (IMG_UINT32) hUniqueTag, ui32Page * SGX_MMU_PAGE_SIZE);
+			if(eErr != PVRSRV_OK)
+			{
+				return eErr;
+			}
+			PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+		}
+	}
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDRegWithFlags(IMG_UINT32 ui32Reg,
+							 IMG_UINT32 ui32Data,
+							 IMG_UINT32	ui32Flags,
+							 IMG_HANDLE hUniqueTag)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING()
+
+
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
+			 "WRW :SGXMEM:$1 :SGXMEM:PA_%8.8lX%8.8lX:0x0\r\n",
+			 (IMG_UINT32)hUniqueTag,
+			 (ui32Data & SGX_MMU_PDE_ADDR_MASK) << SGX_MMU_PDE_ADDR_ALIGNSHIFT);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "SHR :SGXMEM:$1 :SGXMEM:$1 0x4\r\n");
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
+			 "WRW :SGXREG:0x%8.8lX: SGXMEM:$1\r\n",
+			 ui32Reg);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+#else
+	eErr = PDumpOSBufprintf(hScript,
+				ui32MaxLen,
+				"WRW :SGXREG:0x%8.8lX :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX\r\n",
+				ui32Reg,
+				(IMG_UINT32) hUniqueTag,
+				(ui32Data & SGX_MMU_PDE_ADDR_MASK) << SGX_MMU_PDE_ADDR_ALIGNSHIFT,
+				ui32Data & ~SGX_MMU_PDE_ADDR_MASK);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+#endif
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDReg	(IMG_UINT32 ui32Reg,
+					 IMG_UINT32 ui32Data,
+					 IMG_HANDLE hUniqueTag)
+{
+	return PDumpPDRegWithFlags(ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS, hUniqueTag);
+}
+
+PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO		*psMemInfo,
+						   IMG_UINT32			ui32Offset,
+						   IMG_UINT32			ui32Value,
+						   IMG_UINT32			ui32Mask,
+						   PDUMP_POLL_OPERATOR	eOperator,
+						   IMG_UINT32			ui32Flags,
+						   IMG_HANDLE			hUniqueTag)
+{
+	#define MEMPOLL_DELAY		(1000)
+	#define MEMPOLL_COUNT		(2000000000 / MEMPOLL_DELAY)
+
+	PVRSRV_ERROR eErr;
+	IMG_UINT32			ui32PageOffset;
+	IMG_UINT8			*pui8LinAddr;
+	IMG_DEV_PHYADDR		sDevPAddr;
+	IMG_DEV_VIRTADDR	sDevVPageAddr;
+	PDUMP_GET_SCRIPT_STRING();
+
+
+	PVR_ASSERT((ui32Offset + sizeof(IMG_UINT32)) <= psMemInfo->ui32AllocSize);
+
+
+
+	eErr = PDumpOSBufprintf(hScript,
+			 ui32MaxLen,
+			 "-- POL :SGXMEM:VA_%8.8lX 0x%8.8lX 0x%8.8lX %d %d %d\r\n",
+			 psMemInfo->sDevVAddr.uiAddr + ui32Offset,
+			 ui32Value,
+			 ui32Mask,
+			 eOperator,
+			 MEMPOLL_COUNT,
+			 MEMPOLL_DELAY);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+
+	pui8LinAddr = psMemInfo->pvLinAddrKM;
+
+
+	pui8LinAddr += ui32Offset;
+
+
+
+
+	PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
+			ui32Offset,
+			pui8LinAddr,
+			&ui32PageOffset);
+
+
+	sDevVPageAddr.uiAddr = psMemInfo->sDevVAddr.uiAddr + ui32Offset - ui32PageOffset;
+
+	PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+
+	BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+
+	sDevPAddr.uiAddr += ui32PageOffset;
+
+	eErr = PDumpOSBufprintf(hScript,
+			 ui32MaxLen,
+			 "POL :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %d %d %d\r\n",
+			 (IMG_UINT32) hUniqueTag,
+			 sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+			 sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+			 ui32Value,
+			 ui32Mask,
+			 eOperator,
+			 MEMPOLL_COUNT,
+			 MEMPOLL_DELAY);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
+						PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+						IMG_UINT32 ui32Offset,
+						IMG_UINT32 ui32Bytes,
+						IMG_UINT32 ui32Flags,
+						IMG_HANDLE hUniqueTag)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32 ui32NumPages;
+	IMG_UINT32 ui32PageByteOffset;
+	IMG_UINT32 ui32BlockBytes;
+	IMG_UINT8* pui8LinAddr;
+	IMG_UINT8* pui8DataLinAddr = IMG_NULL;
+	IMG_DEV_VIRTADDR sDevVPageAddr;
+	IMG_DEV_VIRTADDR sDevVAddr;
+	IMG_DEV_PHYADDR sDevPAddr;
+	IMG_UINT32 ui32ParamOutPos;
+
+	PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+
+	PVR_ASSERT((ui32Offset + ui32Bytes) <= psMemInfo->ui32AllocSize);
+
+	if (!PDumpOSJTInitialised())
+	{
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	if (ui32Bytes == 0 || PDumpOSIsSuspended())
+	{
+		return PVRSRV_OK;
+	}
+
+
+	if(pvAltLinAddr)
+	{
+		pui8DataLinAddr = pvAltLinAddr;
+	}
+	else if(psMemInfo->pvLinAddrKM)
+	{
+		pui8DataLinAddr = (IMG_UINT8 *)psMemInfo->pvLinAddrKM + ui32Offset;
+	}
+	pui8LinAddr = (IMG_UINT8 *)psMemInfo->pvLinAddrKM;
+	sDevVAddr = psMemInfo->sDevVAddr;
+
+
+	sDevVAddr.uiAddr += ui32Offset;
+	pui8LinAddr += ui32Offset;
+
+	PVR_ASSERT(pui8DataLinAddr);
+
+	PDumpOSCheckForSplitting(PDumpOSGetStream(PDUMP_STREAM_PARAM2), ui32Bytes, ui32Flags);
+
+	ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+
+
+	if(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+						pui8DataLinAddr,
+						ui32Bytes,
+						ui32Flags))
+	{
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	if (PDumpOSGetParamFileNum() == 0)
+	{
+		eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm");
+	}
+	else
+	{
+		eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%%lu.prm", PDumpOSGetParamFileNum());
+	}
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+
+
+
+	eErr = PDumpOSBufprintf(hScript,
+			 ui32MaxLenScript,
+			 "-- LDB :SGXMEM:VA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %s\r\n",
+			 (IMG_UINT32)hUniqueTag,
+			 psMemInfo->sDevVAddr.uiAddr,
+			 ui32Offset,
+			 ui32Bytes,
+			 ui32ParamOutPos,
+			 pszFileName);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+
+
+
+	PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
+			ui32Offset,
+			pui8LinAddr,
+			&ui32PageByteOffset);
+	ui32NumPages = (ui32PageByteOffset + ui32Bytes + HOST_PAGESIZE() - 1) / HOST_PAGESIZE();
+
+	while(ui32NumPages)
+	{
+#if 0
+		IMG_UINT32 ui32BlockBytes = MIN(ui32BytesRemaining, PAGE_SIZE);
+		CpuPAddr = OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle,
+						 ui32CurrentOffset);
+#endif
+		ui32NumPages--;
+
+
+		sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
+
+		PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+
+		BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+
+		sDevPAddr.uiAddr += ui32PageByteOffset;
+#if 0
+		if(ui32PageByteOffset)
+		{
+		    ui32BlockBytes =
+			MIN(ui32BytesRemaining, PAGE_ALIGN(CpuPAddr.uiAddr) - CpuPAddr.uiAddr);
+
+		    ui32PageByteOffset = 0;
+		}
+#endif
+
+		if (ui32PageByteOffset + ui32Bytes > HOST_PAGESIZE())
+		{
+
+			ui32BlockBytes = HOST_PAGESIZE() - ui32PageByteOffset;
+		}
+		else
+		{
+
+			ui32BlockBytes = ui32Bytes;
+		}
+
+		eErr = PDumpOSBufprintf(hScript,
+					 ui32MaxLenScript,
+					 "LDB :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %s\r\n",
+					 (IMG_UINT32) hUniqueTag,
+					 sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+					 sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+					 ui32BlockBytes,
+					 ui32ParamOutPos,
+					 pszFileName);
+		if(eErr != PVRSRV_OK)
+		{
+			return eErr;
+		}
+		PDumpOSWriteString2(hScript, ui32Flags);
+
+
+
+
+		ui32PageByteOffset = 0;
+
+		ui32Bytes -= ui32BlockBytes;
+
+		sDevVAddr.uiAddr += ui32BlockBytes;
+
+		pui8LinAddr += ui32BlockBytes;
+
+		ui32ParamOutPos += ui32BlockBytes;
+	}
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMem2KM(PVRSRV_DEVICE_TYPE eDeviceType,
+						 IMG_CPU_VIRTADDR pvLinAddr,
+						 IMG_UINT32 ui32Bytes,
+						 IMG_UINT32 ui32Flags,
+						 IMG_BOOL bInitialisePages,
+						 IMG_HANDLE hUniqueTag1,
+						 IMG_HANDLE hUniqueTag2)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32 ui32NumPages;
+	IMG_UINT32 ui32PageOffset;
+	IMG_UINT32 ui32BlockBytes;
+	IMG_UINT8* pui8LinAddr;
+	IMG_DEV_PHYADDR sDevPAddr;
+	IMG_CPU_PHYADDR sCpuPAddr;
+	IMG_UINT32 ui32Offset;
+	IMG_UINT32 ui32ParamOutPos;
+
+	PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+	if (!pvLinAddr || !PDumpOSJTInitialised())
+	{
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	if (PDumpOSIsSuspended())
+	{
+		return PVRSRV_OK;
+	}
+
+	PDumpOSCheckForSplitting(PDumpOSGetStream(PDUMP_STREAM_PARAM2), ui32Bytes, ui32Flags);
+
+	ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+	if (bInitialisePages)
+	{
+
+
+
+		if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+							pvLinAddr,
+							ui32Bytes,
+							PDUMP_FLAGS_CONTINUOUS))
+		{
+			return PVRSRV_ERROR_GENERIC;
+		}
+
+		if (PDumpOSGetParamFileNum() == 0)
+		{
+			eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm");
+		}
+		else
+		{
+			eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%%lu.prm", PDumpOSGetParamFileNum());
+		}
+		if(eErr != PVRSRV_OK)
+		{
+			return eErr;
+		}
+	}
+
+
+
+
+	ui32PageOffset	= (IMG_UINT32) pvLinAddr & (HOST_PAGESIZE() - 1);
+	ui32NumPages	= (ui32PageOffset + ui32Bytes + HOST_PAGESIZE() - 1) / HOST_PAGESIZE();
+	pui8LinAddr		= (IMG_UINT8*) pvLinAddr;
+
+	while (ui32NumPages)
+	{
+		ui32NumPages--;
+		sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
+		sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+
+
+		if (ui32PageOffset + ui32Bytes > HOST_PAGESIZE())
+		{
+
+			ui32BlockBytes = HOST_PAGESIZE() - ui32PageOffset;
+		}
+		else
+		{
+
+			ui32BlockBytes = ui32Bytes;
+		}
+
+
+
+		if (bInitialisePages)
+		{
+			eErr = PDumpOSBufprintf(hScript,
+					 ui32MaxLenScript,
+					 "LDB :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %s\r\n",
+					 (IMG_UINT32) hUniqueTag1,
+					 sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+					 sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+					 ui32BlockBytes,
+					 ui32ParamOutPos,
+					 pszFileName);
+			if(eErr != PVRSRV_OK)
+			{
+				return eErr;
+			}
+			PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+		}
+		else
+		{
+			for (ui32Offset = 0; ui32Offset < ui32BlockBytes; ui32Offset += sizeof(IMG_UINT32))
+			{
+				IMG_UINT32 ui32PTE = *((IMG_UINT32 *) (pui8LinAddr + ui32Offset));
+
+				if ((ui32PTE & SGX_MMU_PDE_ADDR_MASK) != 0)
+				{
+#if defined(SGX_FEATURE_36BIT_MMU)
+					eErr = PDumpOSBufprintf(hScript,
+							ui32MaxLenScript,
+							 "WRW :SGXMEM:$1 :SGXMEM:PA_%8.8lX%8.8lX:0x0\r\n",
+							 (IMG_UINT32)hUniqueTag2,
+							 (ui32PTE & SGX_MMU_PDE_ADDR_MASK) << SGX_MMU_PTE_ADDR_ALIGNSHIFT);
+					if(eErr != PVRSRV_OK)
+					{
+						return eErr;
+					}
+					PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+					eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "SHR :SGXMEM:$1 :SGXMEM:$1 0x4\r\n");
+					if(eErr != PVRSRV_OK)
+					{
+						return eErr;
+					}
+					PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+					eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "OR :SGXMEM:$1 :SGXMEM:$1 0x%8.8lX\r\n", ui32PTE & ~SGX_MMU_PDE_ADDR_MASK);
+					if(eErr != PVRSRV_OK)
+					{
+						return eErr;
+					}
+					PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+					eErr = PDumpOSBufprintf(hScript,
+							ui32MaxLenScript,
+							 "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:$1\r\n",
+							 (IMG_UINT32)hUniqueTag1,
+							 (sDevPAddr.uiAddr + ui32Offset) & ~(SGX_MMU_PAGE_MASK),
+							 (sDevPAddr.uiAddr + ui32Offset) & (SGX_MMU_PAGE_MASK));
+					if(eErr != PVRSRV_OK)
+					{
+						return eErr;
+					}
+					PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+#else
+					eErr = PDumpOSBufprintf(hScript,
+							ui32MaxLenScript,
+							 "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX\r\n",
+							 (IMG_UINT32) hUniqueTag1,
+							 (sDevPAddr.uiAddr + ui32Offset) & ~(SGX_MMU_PAGE_MASK),
+							 (sDevPAddr.uiAddr + ui32Offset) & (SGX_MMU_PAGE_MASK),
+							 (IMG_UINT32) hUniqueTag2,
+							 (ui32PTE & SGX_MMU_PDE_ADDR_MASK) << SGX_MMU_PTE_ADDR_ALIGNSHIFT,
+							 ui32PTE & ~SGX_MMU_PDE_ADDR_MASK);
+					if(eErr != PVRSRV_OK)
+					{
+						return eErr;
+					}
+#endif
+				}
+				else
+				{
+					PVR_ASSERT((ui32PTE & SGX_MMU_PTE_VALID) == 0UL);
+					eErr = PDumpOSBufprintf(hScript,
+							ui32MaxLenScript,
+							 "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX%8.8lX\r\n",
+							 (IMG_UINT32) hUniqueTag1,
+							 (sDevPAddr.uiAddr + ui32Offset) & ~(SGX_MMU_PAGE_MASK),
+							 (sDevPAddr.uiAddr + ui32Offset) & (SGX_MMU_PAGE_MASK),
+							 (ui32PTE << SGX_MMU_PTE_ADDR_ALIGNSHIFT),
+							 (IMG_UINT32) hUniqueTag2);
+					if(eErr != PVRSRV_OK)
+					{
+						return eErr;
+					}
+				}
+				PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+			}
+		}
+
+
+
+
+		ui32PageOffset = 0;
+
+		ui32Bytes -= ui32BlockBytes;
+
+		pui8LinAddr += ui32BlockBytes;
+
+		ui32ParamOutPos += ui32BlockBytes;
+	}
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+							   IMG_UINT32 ui32Offset,
+							   IMG_DEV_PHYADDR sPDDevPAddr,
+							   IMG_HANDLE hUniqueTag1,
+							   IMG_HANDLE hUniqueTag2)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32 ui32PageByteOffset;
+	IMG_DEV_VIRTADDR sDevVAddr;
+	IMG_DEV_VIRTADDR sDevVPageAddr;
+	IMG_DEV_PHYADDR sDevPAddr;
+
+	PDUMP_GET_SCRIPT_STRING();
+
+	if(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+						(IMG_UINT8 *)&sPDDevPAddr,
+						sizeof(IMG_DEV_PHYADDR),
+						PDUMP_FLAGS_CONTINUOUS))
+	{
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	sDevVAddr = psMemInfo->sDevVAddr;
+	ui32PageByteOffset = sDevVAddr.uiAddr & (SGX_MMU_PAGE_MASK);
+
+	sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
+	PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+	BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+	sDevPAddr.uiAddr += ui32PageByteOffset + ui32Offset;
+
+	if ((sPDDevPAddr.uiAddr & SGX_MMU_PDE_ADDR_MASK) != 0UL)
+	{
+#if defined(SGX_FEATURE_36BIT_MMU)
+		eErr = PDumpOSBufprintf(hScript,
+				ui32MaxLen,
+				 "WRW :SGXMEM:$1 :SGXMEM:PA_%8.8lX%8.8lX:0x0\r\n",
+				 (IMG_UINT32)hUniqueTag2,
+				 sPDDevPAddr.uiAddr);
+		if(eErr != PVRSRV_OK)
+		{
+			return eErr;
+		}
+		PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+		eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "AND  :SGXMEM:$2 :SGXMEM:$1 0xFFFFFFFF\r\n");
+		if(eErr != PVRSRV_OK)
+		{
+			return eErr;
+		}
+		PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+		eErr = PDumpOSBufprintf(hScript,
+				ui32MaxLen,
+				 "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:$2\r\n",
+				 (IMG_UINT32)hUniqueTag1,
+				 (sDevPAddr.uiAddr) & ~(SGX_MMU_PAGE_MASK),
+				 (sDevPAddr.uiAddr) & (SGX_MMU_PAGE_MASK));
+		if(eErr != PVRSRV_OK)
+		{
+			return eErr;
+		}
+		PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+		eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "SHR :SGXMEM:$2 :SGXMEM:$1 0x20\r\n");
+		if(eErr != PVRSRV_OK)
+		{
+			return eErr;
+		}
+		PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+		eErr = PDumpOSBufprintf(hScript,
+				ui32MaxLen,
+				 "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:$2\r\n",
+				 (IMG_UINT32)hUniqueTag1,
+				 (sDevPAddr.uiAddr + 4) & ~(SGX_MMU_PAGE_MASK),
+				 (sDevPAddr.uiAddr + 4) & (SGX_MMU_PAGE_MASK));
+		if(eErr != PVRSRV_OK)
+		{
+			return eErr;
+		}
+		PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+#else
+		eErr = PDumpOSBufprintf(hScript,
+				 ui32MaxLen,
+				 "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX\r\n",
+				 (IMG_UINT32) hUniqueTag1,
+				 sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+				 sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+				 (IMG_UINT32) hUniqueTag2,
+				 sPDDevPAddr.uiAddr & SGX_MMU_PDE_ADDR_MASK,
+				 sPDDevPAddr.uiAddr & ~SGX_MMU_PDE_ADDR_MASK);
+		if(eErr != PVRSRV_OK)
+		{
+			return eErr;
+		}
+#endif
+	}
+	else
+	{
+		PVR_ASSERT(!(sDevPAddr.uiAddr & SGX_MMU_PTE_VALID));
+		eErr = PDumpOSBufprintf(hScript,
+				 ui32MaxLen,
+				 "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX\r\n",
+				 (IMG_UINT32) hUniqueTag1,
+				 sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+				 sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+				 sPDDevPAddr.uiAddr);
+		if(eErr != PVRSRV_OK)
+		{
+			return eErr;
+		}
+	}
+	PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_MSG_STRING();
+	PDUMP_DBG(("PDumpCommentKM"));
+
+
+	if (!PDumpOSWriteString2("-- ", ui32Flags))
+	{
+		if(ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+		{
+			return PVRSRV_ERROR_GENERIC;
+		}
+		else
+		{
+			return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+		}
+	}
+
+
+	eErr = PDumpOSBufprintf(hMsg, ui32MaxLen, "%s", pszComment);
+	if( (eErr != PVRSRV_OK) &&
+		(eErr != PVRSRV_ERROR_PDUMP_BUF_OVERFLOW))
+	{
+		return eErr;
+	}
+
+
+	PDumpOSVerifyLineEnding(hMsg, ui32MaxLen);
+	PDumpOSWriteString2(hMsg, ui32Flags);
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags, IMG_CHAR * pszFormat, ...)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_va_list ap;
+	PDUMP_GET_MSG_STRING();
+
+
+	PDUMP_va_start(ap, pszFormat);
+	eErr = PDumpOSVSprintf(hMsg, ui32MaxLen, pszFormat, ap);
+	PDUMP_va_end(ap);
+
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	return PDumpCommentKM(hMsg, ui32Flags);
+}
+
+PVRSRV_ERROR PDumpComment(IMG_CHAR *pszFormat, ...)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_va_list ap;
+	PDUMP_GET_MSG_STRING();
+
+
+	PDUMP_va_start(ap, pszFormat);
+	eErr = PDumpOSVSprintf(hMsg, ui32MaxLen, pszFormat, ap);
+	PDUMP_va_end(ap);
+
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	return PDumpCommentKM(hMsg, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32	ui32MsgLen;
+	PDUMP_GET_MSG_STRING();
+
+
+	eErr = PDumpOSBufprintf(hMsg, ui32MaxLen, "%s", pszString);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+
+
+	PDumpOSVerifyLineEnding(hMsg, ui32MaxLen);
+	ui32MsgLen = PDumpOSBuflen(hMsg, ui32MaxLen);
+
+	if	(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_DRIVERINFO),
+						  (IMG_UINT8 *)hMsg,
+						  ui32MsgLen,
+						  ui32Flags))
+	{
+		if	(ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+		{
+			return PVRSRV_ERROR_GENERIC;
+		}
+		else
+		{
+			return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpBitmapKM(	IMG_CHAR *pszFileName,
+							IMG_UINT32 ui32FileOffset,
+							IMG_UINT32 ui32Width,
+							IMG_UINT32 ui32Height,
+							IMG_UINT32 ui32StrideInBytes,
+							IMG_DEV_VIRTADDR sDevBaseAddr,
+							IMG_UINT32 ui32Size,
+							PDUMP_PIXEL_FORMAT ePixelFormat,
+							PDUMP_MEM_FORMAT eMemFormat,
+							IMG_UINT32 ui32PDumpFlags)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING();
+	PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump bitmap of render\r\n");
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+
+	eErr = PDumpOSBufprintf(hScript,
+				ui32MaxLen,
+				"SII %s %s.bin :SGXMEM:v%x:0x%08lX 0x%08lX 0x%08lX 0x%08X 0x%08lX 0x%08lX 0x%08lX 0x%08X\r\n",
+				pszFileName,
+				pszFileName,
+				PDUMP_DATAMASTER_PIXEL,
+				sDevBaseAddr.uiAddr,
+				ui32Size,
+				ui32FileOffset,
+				ePixelFormat,
+				ui32Width,
+				ui32Height,
+				ui32StrideInBytes,
+				eMemFormat);
+#else
+	eErr = PDumpOSBufprintf(hScript,
+				ui32MaxLen,
+				"SII %s %s.bin :SGXMEM:v:0x%08lX 0x%08lX 0x%08lX 0x%08X 0x%08lX 0x%08lX 0x%08lX 0x%08X\r\n",
+				pszFileName,
+				pszFileName,
+				sDevBaseAddr.uiAddr,
+				ui32Size,
+				ui32FileOffset,
+				ePixelFormat,
+				ui32Width,
+				ui32Height,
+				ui32StrideInBytes,
+				eMemFormat);
+#endif
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+
+	PDumpOSWriteString2( hScript, ui32PDumpFlags);
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpReadRegKM		(	IMG_CHAR *pszFileName,
+									IMG_UINT32 ui32FileOffset,
+									IMG_UINT32 ui32Address,
+									IMG_UINT32 ui32Size,
+									IMG_UINT32 ui32PDumpFlags)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING();
+
+	PVR_UNREFERENCED_PARAMETER(ui32Size);
+
+	eErr = PDumpOSBufprintf(hScript,
+			ui32MaxLen,
+			"SAB :SGXREG:0x%08lX 0x%08lX %s\r\n",
+			ui32Address,
+			ui32FileOffset,
+			pszFileName);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+
+	PDumpOSWriteString2( hScript, ui32PDumpFlags);
+
+	return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpTestNextFrame(IMG_UINT32 ui32CurrentFrame)
+{
+	IMG_BOOL	bFrameDumped;
+
+
+
+	(IMG_VOID) PDumpSetFrameKM(ui32CurrentFrame + 1);
+	bFrameDumped = PDumpIsCaptureFrameKM();
+	(IMG_VOID) PDumpSetFrameKM(ui32CurrentFrame);
+
+	return bFrameDumped;
+}
+
+static PVRSRV_ERROR PDumpSignatureRegister	(IMG_CHAR	*pszFileName,
+									 IMG_UINT32		ui32Address,
+									 IMG_UINT32		ui32Size,
+									 IMG_UINT32		*pui32FileOffset,
+									 IMG_UINT32		ui32Flags)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING();
+
+	eErr = PDumpOSBufprintf(hScript,
+			ui32MaxLen,
+			"SAB :SGXREG:0x%08X 0x%08X %s\r\n",
+			ui32Address,
+			*pui32FileOffset,
+			pszFileName);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+
+	PDumpOSWriteString2(hScript, ui32Flags);
+	*pui32FileOffset += ui32Size;
+	return PVRSRV_OK;
+}
+
+static IMG_VOID PDumpRegisterRange(IMG_CHAR *pszFileName,
+		IMG_UINT32 *pui32Registers,
+		IMG_UINT32  ui32NumRegisters,
+		IMG_UINT32 *pui32FileOffset,
+		IMG_UINT32	ui32Size,
+		IMG_UINT32	ui32Flags)
+{
+	IMG_UINT32 i;
+	for (i = 0; i < ui32NumRegisters; i++)
+	{
+		PDumpSignatureRegister(pszFileName, pui32Registers[i], ui32Size, pui32FileOffset, ui32Flags);
+	}
+}
+
+PVRSRV_ERROR PDump3DSignatureRegisters(IMG_UINT32 ui32DumpFrameNum,
+			IMG_BOOL bLastFrame,
+			IMG_UINT32 *pui32Registers,
+			IMG_UINT32 ui32NumRegisters)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32	ui32FileOffset, ui32Flags;
+
+	PDUMP_GET_FILE_STRING();
+
+	ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+	ui32FileOffset = 0;
+
+	PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump 3D signature registers\r\n");
+	eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%lu_3d.sig", ui32DumpFrameNum);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+
+	PDumpRegisterRange(pszFileName, pui32Registers, ui32NumRegisters, &ui32FileOffset, sizeof(IMG_UINT32), ui32Flags);
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpTASignatureRegisters	(IMG_UINT32 ui32DumpFrameNum,
+			 IMG_UINT32	ui32TAKickCount,
+			 IMG_BOOL	bLastFrame,
+			 IMG_UINT32 *pui32Registers,
+			 IMG_UINT32 ui32NumRegisters)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32	ui32FileOffset, ui32Flags;
+
+	PDUMP_GET_FILE_STRING();
+
+	ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+	ui32FileOffset = ui32TAKickCount * ui32NumRegisters * sizeof(IMG_UINT32);
+
+	PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump TA signature registers\r\n");
+	eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%lu_ta.sig", ui32DumpFrameNum);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+
+	PDumpRegisterRange(pszFileName, pui32Registers, ui32NumRegisters, &ui32FileOffset, sizeof(IMG_UINT32), ui32Flags);
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCounterRegisters (IMG_UINT32 ui32DumpFrameNum,
+								IMG_BOOL	bLastFrame,
+								IMG_UINT32 *pui32Registers,
+								IMG_UINT32 ui32NumRegisters)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32	ui32FileOffset, ui32Flags;
+
+	PDUMP_GET_FILE_STRING();
+
+	ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0UL;
+	ui32FileOffset = 0UL;
+
+	PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump counter registers\r\n");
+	eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%lu.perf", ui32DumpFrameNum);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+
+	PDumpRegisterRange(pszFileName, pui32Registers, ui32NumRegisters, &ui32FileOffset, sizeof(IMG_UINT32), ui32Flags);
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpRegRead(const IMG_UINT32 ui32RegOffset, IMG_UINT32 ui32Flags)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING();
+
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "RDW :SGXREG:0x%lX\r\n", ui32RegOffset);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCycleCountRegRead(const IMG_UINT32 ui32RegOffset, IMG_BOOL bLastFrame)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING();
+
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "RDW :SGXREG:0x%lX\r\n", ui32RegOffset);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpHWPerfCBKM (IMG_CHAR			*pszFileName,
+						  IMG_UINT32		ui32FileOffset,
+						  IMG_DEV_VIRTADDR	sDevBaseAddr,
+						  IMG_UINT32 		ui32Size,
+						  IMG_UINT32 		ui32PDumpFlags)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING();
+	PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump Hardware Performance Circular Buffer\r\n");
+
+	eErr = PDumpOSBufprintf(hScript,
+				ui32MaxLen,
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+				"SAB :SGXMEM:v%x:0x%08lX 0x%08lX 0x%08lX %s.bin\r\n",
+				PDUMP_DATAMASTER_EDM,
+#else
+				"SAB :SGXMEM:v:0x%08lX 0x%08lX 0x%08lX %s.bin\r\n",
+#endif
+				sDevBaseAddr.uiAddr,
+				ui32Size,
+				ui32FileOffset,
+				pszFileName);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+
+	PDumpOSWriteString2(hScript, ui32PDumpFlags);
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO		psROffMemInfo,
+			  IMG_UINT32					ui32ROffOffset,
+			  IMG_UINT32					ui32WPosVal,
+			  IMG_UINT32					ui32PacketSize,
+			  IMG_UINT32					ui32BufferSize,
+			  IMG_UINT32					ui32Flags,
+			  IMG_HANDLE					hUniqueTag)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32			ui32PageOffset;
+	IMG_UINT8			*pui8LinAddr;
+	IMG_DEV_VIRTADDR	sDevVAddr;
+	IMG_DEV_PHYADDR		sDevPAddr;
+	IMG_DEV_VIRTADDR 	sDevVPageAddr;
+
+
+	PDUMP_GET_SCRIPT_STRING();
+
+
+	PVR_ASSERT((ui32ROffOffset + sizeof(IMG_UINT32)) <= psROffMemInfo->ui32AllocSize);
+
+	pui8LinAddr = psROffMemInfo->pvLinAddrKM;
+	sDevVAddr = psROffMemInfo->sDevVAddr;
+
+
+	pui8LinAddr += ui32ROffOffset;
+	sDevVAddr.uiAddr += ui32ROffOffset;
+
+
+
+
+
+
+	PDumpOSCPUVAddrToPhysPages(psROffMemInfo->sMemBlk.hOSMemHandle,
+			ui32ROffOffset,
+			pui8LinAddr,
+			&ui32PageOffset);
+
+
+	sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageOffset;
+
+	PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+
+	BM_GetPhysPageAddr(psROffMemInfo, sDevVPageAddr, &sDevPAddr);
+
+
+	sDevPAddr.uiAddr += ui32PageOffset;
+
+	eErr = PDumpOSBufprintf(hScript,
+			 ui32MaxLen,
+			 "CBP :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX 0x%8.8lX\r\n",
+			 (IMG_UINT32) hUniqueTag,
+			 sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+			 sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+			 ui32WPosVal,
+			 ui32PacketSize,
+			 ui32BufferSize);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING();
+	PDUMP_DBG(("PDumpIDLWithFlags"));
+
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "IDL %lu\r\n", ui32Clocks);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks)
+{
+	return PDumpIDLWithFlags(ui32Clocks, PDUMP_FLAGS_CONTINUOUS);
+}
+#endif
+
+
+PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+						IMG_PVOID pvAltLinAddrUM,
+						IMG_PVOID pvLinAddrUM,
+						PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+						IMG_UINT32 ui32Offset,
+						IMG_UINT32 ui32Bytes,
+						IMG_UINT32 ui32Flags,
+						IMG_HANDLE hUniqueTag)
+{
+	IMG_VOID *pvAddrUM;
+	IMG_VOID *pvAddrKM;
+	IMG_UINT32 ui32BytesDumped;
+	IMG_UINT32 ui32CurrentOffset;
+
+	if (psMemInfo->pvLinAddrKM != IMG_NULL && pvAltLinAddrUM == IMG_NULL)
+	{
+
+		return PDumpMemKM(IMG_NULL,
+					   psMemInfo,
+					   ui32Offset,
+					   ui32Bytes,
+					   ui32Flags,
+					   hUniqueTag);
+	}
+
+	pvAddrUM = (pvAltLinAddrUM != IMG_NULL) ? pvAltLinAddrUM : ((pvLinAddrUM != IMG_NULL) ? VPTR_PLUS(pvLinAddrUM, ui32Offset) : IMG_NULL);
+
+	pvAddrKM = GetTempBuffer();
+
+
+	PVR_ASSERT(pvAddrUM != IMG_NULL && pvAddrKM != IMG_NULL);
+	if (pvAddrUM == IMG_NULL || pvAddrKM == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: Nothing to dump"));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	if (ui32Bytes > PDUMP_TEMP_BUFFER_SIZE)
+	{
+		PDumpCommentWithFlags(ui32Flags, "Dumping 0x%8.8lx bytes of memory, in blocks of 0x%8.8lx bytes", ui32Bytes, (IMG_UINT32)PDUMP_TEMP_BUFFER_SIZE);
+	}
+
+	ui32CurrentOffset = ui32Offset;
+	for (ui32BytesDumped = 0; ui32BytesDumped < ui32Bytes;)
+	{
+		PVRSRV_ERROR eError;
+		IMG_UINT32 ui32BytesToDump = MIN(PDUMP_TEMP_BUFFER_SIZE, ui32Bytes - ui32BytesDumped);
+
+		eError = OSCopyFromUser(psPerProc,
+					   pvAddrKM,
+					   pvAddrUM,
+					   ui32BytesToDump);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: OSCopyFromUser failed (%d), eError"));
+			return PVRSRV_ERROR_GENERIC;
+		}
+
+		eError = PDumpMemKM(pvAddrKM,
+					   psMemInfo,
+					   ui32CurrentOffset,
+					   ui32BytesToDump,
+					   ui32Flags,
+					   hUniqueTag);
+
+		if (eError != PVRSRV_OK)
+		{
+
+			if (ui32BytesDumped != 0)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: PDumpMemKM failed (%d)", eError));
+			}
+/*			FIXME: This assert causes kernel to crash when using PDUMP */
+/*			PVR_ASSERT(ui32BytesDumped == 0); */
+			return eError;
+		}
+
+		VPTR_INC(pvAddrUM, ui32BytesToDump);
+		ui32CurrentOffset += ui32BytesToDump;
+		ui32BytesDumped += ui32BytesToDump;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR _PdumpAllocMMUContext(IMG_UINT32 *pui32MMUContextID)
+{
+	IMG_UINT32 i;
+
+
+	for(i=0; i<MAX_PDUMP_MMU_CONTEXTS; i++)
+	{
+		if((gui16MMUContextUsage & (1U << i)) == 0)
+		{
+
+			gui16MMUContextUsage |= 1U << i;
+			*pui32MMUContextID = i;
+			return PVRSRV_OK;
+		}
+	}
+
+	PVR_DPF((PVR_DBG_ERROR, "_PdumpAllocMMUContext: no free MMU context ids"));
+
+	return PVRSRV_ERROR_GENERIC;
+}
+
+
+static PVRSRV_ERROR _PdumpFreeMMUContext(IMG_UINT32 ui32MMUContextID)
+{
+	if(ui32MMUContextID < MAX_PDUMP_MMU_CONTEXTS)
+	{
+
+		gui16MMUContextUsage &= ~(1U << ui32MMUContextID);
+		return PVRSRV_OK;
+	}
+
+	PVR_DPF((PVR_DBG_ERROR, "_PdumpFreeMMUContext: MMU context ids invalid"));
+
+	return PVRSRV_ERROR_GENERIC;
+}
+
+
+PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+								IMG_CHAR *pszMemSpace,
+								IMG_UINT32 *pui32MMUContextID,
+								IMG_UINT32 ui32MMUType,
+								IMG_HANDLE hUniqueTag1,
+								IMG_VOID *pvPDCPUAddr)
+{
+	IMG_UINT8 *pui8LinAddr = (IMG_UINT8 *)pvPDCPUAddr;
+	IMG_CPU_PHYADDR sCpuPAddr;
+	IMG_DEV_PHYADDR sDevPAddr;
+	IMG_UINT32 ui32MMUContextID;
+	PVRSRV_ERROR eError;
+
+	eError = _PdumpAllocMMUContext(&ui32MMUContextID);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpSetMMUContext: _PdumpAllocMMUContext failed: %d", eError));
+		return eError;
+	}
+
+
+	sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
+	sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+
+	sDevPAddr.uiAddr &= ~((PVRSRV_4K_PAGE_SIZE) -1);
+
+	PDumpComment("Set MMU Context\r\n");
+
+	PDumpComment("MMU :%s:v%d %d :%s:PA_%8.8lX%8.8lX\r\n",
+						pszMemSpace,
+						ui32MMUContextID,
+						ui32MMUType,
+						pszMemSpace,
+						hUniqueTag1,
+						sDevPAddr.uiAddr);
+
+
+	*pui32MMUContextID = ui32MMUContextID;
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+								IMG_CHAR *pszMemSpace,
+								IMG_UINT32 ui32MMUContextID,
+								IMG_UINT32 ui32MMUType)
+{
+	PVRSRV_ERROR eError;
+
+	PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+
+	PDumpComment("Clear MMU Context for memory space %s\r\n", pszMemSpace);
+
+	PDumpComment("MMU :%s:v%d %d\r\n",
+						pszMemSpace,
+						ui32MMUContextID,
+						ui32MMUType);
+
+	eError = _PdumpFreeMMUContext(ui32MMUContextID);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpClearMMUContext: _PdumpFreeMMUContext failed: %d", eError));
+		return eError;
+	}
+
+	return PVRSRV_OK;
+}
+
+#else
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/perproc.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/perproc.c
new file mode 100644
index 0000000..64e8faf
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/perproc.c
@@ -0,0 +1,279 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "resman.h"
+#include "handle.h"
+#include "perproc.h"
+#include "osperproc.h"
+
+#define	HASH_TAB_INIT_SIZE 32
+
+static HASH_TABLE *psHashTab = IMG_NULL;
+
+static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_ERROR eError;
+	IMG_UINTPTR_T uiPerProc;
+
+	PVR_ASSERT(psPerProc != IMG_NULL);
+
+	if (psPerProc == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: invalid parameter"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	uiPerProc = HASH_Remove(psHashTab, (IMG_UINTPTR_T)psPerProc->ui32PID);
+	if (uiPerProc == 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't find process in per-process data hash table"));
+
+		PVR_ASSERT(psPerProc->ui32PID == 0);
+	}
+	else
+	{
+		PVR_ASSERT((PVRSRV_PER_PROCESS_DATA *)uiPerProc == psPerProc);
+		PVR_ASSERT(((PVRSRV_PER_PROCESS_DATA *)uiPerProc)->ui32PID == psPerProc->ui32PID);
+	}
+
+
+	if (psPerProc->psHandleBase != IMG_NULL)
+	{
+		eError = PVRSRVFreeHandleBase(psPerProc->psHandleBase);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free handle base for process (%d)", eError));
+			return eError;
+		}
+	}
+
+
+	if (psPerProc->hPerProcData != IMG_NULL)
+	{
+		eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE, psPerProc->hPerProcData, PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't release per-process data handle (%d)", eError));
+			return eError;
+		}
+	}
+
+
+	eError = OSPerProcessPrivateDataDeInit(psPerProc->hOsPrivateData);
+	if (eError != PVRSRV_OK)
+	{
+		 PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: OSPerProcessPrivateDataDeInit failed (%d)", eError));
+		return eError;
+	}
+
+	eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+		sizeof(*psPerProc),
+		psPerProc,
+		psPerProc->hBlockAlloc);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free per-process data (%d)", eError));
+		return eError;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID)
+{
+	PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+	PVR_ASSERT(psHashTab != IMG_NULL);
+
+
+	psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+	return psPerProc;
+}
+
+
+PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32	ui32PID)
+{
+	PVRSRV_PER_PROCESS_DATA *psPerProc;
+	IMG_HANDLE hBlockAlloc;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	PVR_ASSERT(psHashTab != IMG_NULL);
+
+
+	psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+
+	if (psPerProc == IMG_NULL)
+	{
+
+		eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+							sizeof(*psPerProc),
+							(IMG_PVOID *)&psPerProc,
+							&hBlockAlloc,
+							"Per Process Data");
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate per-process data (%d)", eError));
+			return eError;
+		}
+		OSMemSet(psPerProc, 0, sizeof(*psPerProc));
+		psPerProc->hBlockAlloc = hBlockAlloc;
+
+		if (!HASH_Insert(psHashTab, (IMG_UINTPTR_T)ui32PID, (IMG_UINTPTR_T)psPerProc))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't insert per-process data into hash table"));
+			eError = PVRSRV_ERROR_GENERIC;
+			goto failure;
+		}
+
+		psPerProc->ui32PID = ui32PID;
+		psPerProc->ui32RefCount = 0;
+
+
+		eError = OSPerProcessPrivateDataInit(&psPerProc->hOsPrivateData);
+		if (eError != PVRSRV_OK)
+		{
+			 PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: OSPerProcessPrivateDataInit failed (%d)", eError));
+			goto failure;
+		}
+
+
+		eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+								   &psPerProc->hPerProcData,
+								   psPerProc,
+								   PVRSRV_HANDLE_TYPE_PERPROC_DATA,
+								   PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle for per-process data (%d)", eError));
+			goto failure;
+		}
+
+
+		eError = PVRSRVAllocHandleBase(&psPerProc->psHandleBase);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle base for process (%d)", eError));
+			goto failure;
+		}
+
+
+		eError = OSPerProcessSetHandleOptions(psPerProc->psHandleBase);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't set handle options (%d)", eError));
+			goto failure;
+		}
+
+
+		eError = PVRSRVResManConnect(psPerProc, &psPerProc->hResManContext);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't register with the resource manager"));
+			goto failure;
+		}
+	}
+
+	psPerProc->ui32RefCount++;
+	PVR_DPF((PVR_DBG_MESSAGE,
+			"PVRSRVPerProcessDataConnect: Process 0x%x has ref-count %d",
+			ui32PID, psPerProc->ui32RefCount));
+
+	return eError;
+
+failure:
+	(IMG_VOID)FreePerProcessData(psPerProc);
+	return eError;
+}
+
+
+IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32	ui32PID)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+	PVR_ASSERT(psHashTab != IMG_NULL);
+
+	psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+	if (psPerProc == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDealloc: Couldn't locate per-process data for PID %u", ui32PID));
+	}
+	else
+	{
+		psPerProc->ui32RefCount--;
+		if (psPerProc->ui32RefCount == 0)
+		{
+			PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVPerProcessDataDisconnect: "
+					"Last close from process 0x%x received", ui32PID));
+
+
+			PVRSRVResManDisconnect(psPerProc->hResManContext, IMG_FALSE);
+
+
+			eError = FreePerProcessData(psPerProc);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: Error freeing per-process data"));
+			}
+		}
+	}
+
+	eError = PVRSRVPurgeHandles(KERNEL_HANDLE_BASE);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: Purge of global handle pool failed (%d)", eError));
+	}
+}
+
+
+PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID)
+{
+	PVR_ASSERT(psHashTab == IMG_NULL);
+
+
+	psHashTab = HASH_Create(HASH_TAB_INIT_SIZE);
+	if (psHashTab == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataInit: Couldn't create per-process data hash table"));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID)
+{
+
+	if (psHashTab != IMG_NULL)
+	{
+
+		HASH_Delete(psHashTab);
+		psHashTab = IMG_NULL;
+	}
+
+	return PVRSRV_OK;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/power.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/power.c
new file mode 100644
index 0000000..b5b8585
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/power.c
@@ -0,0 +1,743 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "pdump_km.h"
+
+#include "lists.h"
+
+DECLARE_LIST_ANY_VA(PVRSRV_POWER_DEV);
+DECLARE_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_INSERT(PVRSRV_POWER_DEV);
+DECLARE_LIST_REMOVE(PVRSRV_POWER_DEV);
+
+IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va);
+
+
+static IMG_BOOL gbInitServerRunning = IMG_FALSE;
+static IMG_BOOL gbInitServerRan = IMG_FALSE;
+static IMG_BOOL gbInitSuccessful = IMG_FALSE;
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState, IMG_BOOL bState)
+{
+
+	switch(eInitServerState)
+	{
+		case PVRSRV_INIT_SERVER_RUNNING:
+			gbInitServerRunning	= bState;
+			break;
+		case PVRSRV_INIT_SERVER_RAN:
+			gbInitServerRan	= bState;
+			break;
+		case PVRSRV_INIT_SERVER_SUCCESSFUL:
+			gbInitSuccessful = bState;
+			break;
+		default:
+			PVR_DPF((PVR_DBG_ERROR,
+				"PVRSRVSetInitServerState : Unknown state %lx", eInitServerState));
+			return PVRSRV_ERROR_GENERIC;
+	}
+
+	return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState)
+{
+	IMG_BOOL	bReturnVal;
+
+	switch(eInitServerState)
+	{
+		case PVRSRV_INIT_SERVER_RUNNING:
+			bReturnVal = gbInitServerRunning;
+			break;
+		case PVRSRV_INIT_SERVER_RAN:
+			bReturnVal = gbInitServerRan;
+			break;
+		case PVRSRV_INIT_SERVER_SUCCESSFUL:
+			bReturnVal = gbInitSuccessful;
+			break;
+		default:
+			PVR_DPF((PVR_DBG_ERROR,
+				"PVRSRVGetInitServerState : Unknown state %lx", eInitServerState));
+			bReturnVal = IMG_FALSE;
+	}
+
+	return bReturnVal;
+}
+
+static IMG_BOOL _IsSystemStatePowered(PVRSRV_SYS_POWER_STATE eSystemPowerState)
+{
+	return (IMG_BOOL)(eSystemPowerState < PVRSRV_SYS_POWER_STATE_D2);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32	ui32CallerID,
+							 IMG_BOOL	bSystemPowerEvent)
+{
+	PVRSRV_ERROR	eError;
+	SYS_DATA		*psSysData;
+	IMG_UINT32		ui32Timeout = 1000000;
+
+#if defined(SUPPORT_LMA)
+
+	ui32Timeout *= 60;
+#endif
+
+	SysAcquireData(&psSysData);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+	eError = SysPowerLockWrap(psSysData);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+#endif
+	do
+	{
+		eError = OSLockResource(&psSysData->sPowerStateChangeResource,
+								ui32CallerID);
+		if (eError == PVRSRV_OK)
+		{
+			break;
+		}
+		else if (ui32CallerID == ISR_ID)
+		{
+
+
+			eError = PVRSRV_ERROR_RETRY;
+			break;
+		}
+
+		OSWaitus(1);
+		ui32Timeout--;
+	} while (ui32Timeout > 0);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+	if (eError != PVRSRV_OK)
+	{
+		SysPowerLockUnwrap(psSysData);
+	}
+#endif
+	if ((eError == PVRSRV_OK) &&
+		!bSystemPowerEvent &&
+		!_IsSystemStatePowered(psSysData->eCurrentPowerState))
+	{
+
+		PVRSRVPowerUnlock(ui32CallerID);
+		eError = PVRSRV_ERROR_RETRY;
+	}
+
+	return eError;
+}
+
+
+IMG_EXPORT
+IMG_VOID PVRSRVPowerUnlock(IMG_UINT32	ui32CallerID)
+{
+	OSUnlockResource(&gpsSysData->sPowerStateChangeResource, ui32CallerID);
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+	SysPowerLockUnwrap(gpsSysData);
+#endif
+}
+
+
+PVRSRV_ERROR PVRSRVDevicePrePowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
+{
+	PVRSRV_DEV_POWER_STATE	eNewDevicePowerState;
+	PVRSRV_ERROR			eError;
+
+
+	IMG_BOOL				bAllDevices;
+	IMG_UINT32				ui32DeviceIndex;
+	PVRSRV_DEV_POWER_STATE	eNewPowerState;
+
+
+	bAllDevices = va_arg(va, IMG_BOOL);
+	ui32DeviceIndex = va_arg(va, IMG_UINT32);
+	eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+
+	if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+	{
+		eNewDevicePowerState = (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) ?
+							psPowerDevice->eDefaultPowerState : eNewPowerState;
+
+		if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
+		{
+			if (psPowerDevice->pfnPrePower != IMG_NULL)
+			{
+
+				eError = psPowerDevice->pfnPrePower(psPowerDevice->hDevCookie,
+													eNewDevicePowerState,
+													psPowerDevice->eCurrentPowerState);
+				if (eError != PVRSRV_OK)
+				{
+					return eError;
+				}
+			}
+
+
+			eError = SysDevicePrePowerState(psPowerDevice->ui32DeviceIndex,
+											eNewDevicePowerState,
+											psPowerDevice->eCurrentPowerState);
+			if (eError != PVRSRV_OK)
+			{
+				return eError;
+			}
+		}
+	}
+
+	return  PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL				bAllDevices,
+										 IMG_UINT32				ui32DeviceIndex,
+										 PVRSRV_DEV_POWER_STATE	eNewPowerState)
+{
+	PVRSRV_ERROR		eError;
+	SYS_DATA			*psSysData;
+
+	SysAcquireData(&psSysData);
+
+
+	eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->psPowerDeviceList,
+														PVRSRVDevicePrePowerStateKM_AnyVaCb,
+														bAllDevices,
+														ui32DeviceIndex,
+														eNewPowerState);
+
+	return eError;
+}
+
+PVRSRV_ERROR PVRSRVDevicePostPowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
+{
+	PVRSRV_DEV_POWER_STATE	eNewDevicePowerState;
+	PVRSRV_ERROR			eError;
+
+
+	IMG_BOOL				bAllDevices;
+	IMG_UINT32				ui32DeviceIndex;
+	PVRSRV_DEV_POWER_STATE	eNewPowerState;
+
+
+	bAllDevices = va_arg(va, IMG_BOOL);
+	ui32DeviceIndex = va_arg(va, IMG_UINT32);
+	eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+
+	if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+	{
+		eNewDevicePowerState = (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) ?
+								psPowerDevice->eDefaultPowerState : eNewPowerState;
+
+		if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
+		{
+
+			eError = SysDevicePostPowerState(psPowerDevice->ui32DeviceIndex,
+											 eNewDevicePowerState,
+											 psPowerDevice->eCurrentPowerState);
+			if (eError != PVRSRV_OK)
+			{
+				return eError;
+			}
+
+			if (psPowerDevice->pfnPostPower != IMG_NULL)
+			{
+
+				eError = psPowerDevice->pfnPostPower(psPowerDevice->hDevCookie,
+													 eNewDevicePowerState,
+													 psPowerDevice->eCurrentPowerState);
+				if (eError != PVRSRV_OK)
+				{
+					return eError;
+				}
+			}
+
+			psPowerDevice->eCurrentPowerState = eNewDevicePowerState;
+		}
+	}
+	return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL					bAllDevices,
+										  IMG_UINT32				ui32DeviceIndex,
+										  PVRSRV_DEV_POWER_STATE	eNewPowerState)
+{
+	PVRSRV_ERROR		eError;
+	SYS_DATA			*psSysData;
+
+	SysAcquireData(&psSysData);
+
+
+	eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->psPowerDeviceList,
+														PVRSRVDevicePostPowerStateKM_AnyVaCb,
+														bAllDevices,
+														ui32DeviceIndex,
+														eNewPowerState);
+
+	return eError;
+}
+
+
+PVRSRV_ERROR PVRSRVSetDevicePowerStateCoreKM(IMG_UINT32				ui32DeviceIndex,
+                                             PVRSRV_DEV_POWER_STATE	eNewPowerState)
+{
+	PVRSRV_ERROR	eError;
+	eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
+	if(eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
+	return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32				ui32DeviceIndex,
+										 PVRSRV_DEV_POWER_STATE	eNewPowerState,
+										 IMG_UINT32				ui32CallerID,
+										 IMG_BOOL				bRetainMutex)
+{
+	PVRSRV_ERROR	eError;
+	SYS_DATA		*psSysData;
+
+	SysAcquireData(&psSysData);
+
+	eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+	if(eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	#if defined(PDUMP)
+	if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+	{
+
+
+
+
+		eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
+		if(eError != PVRSRV_OK)
+		{
+			goto Exit;
+		}
+
+		eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
+
+		if (eError != PVRSRV_OK)
+		{
+			goto Exit;
+		}
+
+		PDUMPSUSPEND();
+	}
+	#endif
+
+	eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
+	if(eError != PVRSRV_OK)
+	{
+		if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+		{
+			PDUMPRESUME();
+		}
+		goto Exit;
+	}
+
+	eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
+
+	if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+	{
+		PDUMPRESUME();
+	}
+
+Exit:
+
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"PVRSRVSetDevicePowerStateKM : Transition to %d FAILED 0x%x", eNewPowerState, eError));
+	}
+
+	if (!bRetainMutex || (eError != PVRSRV_OK))
+	{
+		PVRSRVPowerUnlock(ui32CallerID);
+	}
+
+	return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+	PVRSRV_ERROR			eError;
+	SYS_DATA				*psSysData;
+	PVRSRV_DEV_POWER_STATE	eNewDevicePowerState;
+
+	SysAcquireData(&psSysData);
+
+
+	eError = PVRSRVPowerLock(KERNEL_ID, IMG_TRUE);
+	if(eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	if (_IsSystemStatePowered(eNewSysPowerState) !=
+		_IsSystemStatePowered(psSysData->eCurrentPowerState))
+	{
+		if (_IsSystemStatePowered(eNewSysPowerState))
+		{
+
+			eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
+		}
+		else
+		{
+			eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
+		}
+
+
+		eError = PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0, eNewDevicePowerState);
+		if (eError != PVRSRV_OK)
+		{
+			goto ErrorExit;
+		}
+	}
+
+	if (eNewSysPowerState != psSysData->eCurrentPowerState)
+	{
+
+		eError = SysSystemPrePowerState(eNewSysPowerState);
+		if (eError != PVRSRV_OK)
+		{
+			goto ErrorExit;
+		}
+	}
+
+	return eError;
+
+ErrorExit:
+
+	PVR_DPF((PVR_DBG_ERROR,
+			"PVRSRVSystemPrePowerStateKM: Transition from %d to %d FAILED 0x%x",
+			psSysData->eCurrentPowerState, eNewSysPowerState, eError));
+
+
+	psSysData->eFailedPowerState = eNewSysPowerState;
+
+	PVRSRVPowerUnlock(KERNEL_ID);
+
+	return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+	PVRSRV_ERROR			eError = PVRSRV_OK;
+	SYS_DATA				*psSysData;
+	PVRSRV_DEV_POWER_STATE	eNewDevicePowerState;
+
+	SysAcquireData(&psSysData);
+
+	if (eNewSysPowerState != psSysData->eCurrentPowerState)
+	{
+
+		eError = SysSystemPostPowerState(eNewSysPowerState);
+		if (eError != PVRSRV_OK)
+		{
+			goto Exit;
+		}
+	}
+
+	if (_IsSystemStatePowered(eNewSysPowerState) !=
+		_IsSystemStatePowered(psSysData->eCurrentPowerState))
+	{
+		if (_IsSystemStatePowered(eNewSysPowerState))
+		{
+
+			eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
+		}
+		else
+		{
+			eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
+		}
+
+
+		eError = PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0, eNewDevicePowerState);
+		if (eError != PVRSRV_OK)
+		{
+			goto Exit;
+		}
+	}
+
+	PVR_DPF((PVR_DBG_MESSAGE,
+			"PVRSRVSystemPostPowerStateKM: System Power Transition from %d to %d OK",
+			psSysData->eCurrentPowerState, eNewSysPowerState));
+
+	psSysData->eCurrentPowerState = eNewSysPowerState;
+
+Exit:
+
+	PVRSRVPowerUnlock(KERNEL_ID);
+
+	if (_IsSystemStatePowered(eNewSysPowerState) &&
+			PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+	{
+
+
+
+		PVRSRVCommandCompleteCallbacks();
+	}
+
+	return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+	PVRSRV_ERROR	eError;
+	SYS_DATA		*psSysData;
+
+	SysAcquireData(&psSysData);
+
+	eError = PVRSRVSystemPrePowerStateKM(eNewSysPowerState);
+	if(eError != PVRSRV_OK)
+	{
+		goto ErrorExit;
+	}
+
+	eError = PVRSRVSystemPostPowerStateKM(eNewSysPowerState);
+	if(eError != PVRSRV_OK)
+	{
+		goto ErrorExit;
+	}
+
+
+	psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
+
+	return PVRSRV_OK;
+
+ErrorExit:
+
+	PVR_DPF((PVR_DBG_ERROR,
+			"PVRSRVSetPowerStateKM: Transition from %d to %d FAILED 0x%x",
+			psSysData->eCurrentPowerState, eNewSysPowerState, eError));
+
+
+	psSysData->eFailedPowerState = eNewSysPowerState;
+
+	return eError;
+}
+
+
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32					ui32DeviceIndex,
+									   PFN_PRE_POWER				pfnPrePower,
+									   PFN_POST_POWER				pfnPostPower,
+									   PFN_PRE_CLOCKSPEED_CHANGE	pfnPreClockSpeedChange,
+									   PFN_POST_CLOCKSPEED_CHANGE	pfnPostClockSpeedChange,
+									   IMG_HANDLE					hDevCookie,
+									   PVRSRV_DEV_POWER_STATE		eCurrentPowerState,
+									   PVRSRV_DEV_POWER_STATE		eDefaultPowerState)
+{
+	PVRSRV_ERROR		eError;
+	SYS_DATA			*psSysData;
+	PVRSRV_POWER_DEV	*psPowerDevice;
+
+	if (pfnPrePower == IMG_NULL &&
+		pfnPostPower == IMG_NULL)
+	{
+		return PVRSRVRemovePowerDevice(ui32DeviceIndex);
+	}
+
+	SysAcquireData(&psSysData);
+
+	eError = OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+						 sizeof(PVRSRV_POWER_DEV),
+						 (IMG_VOID **)&psPowerDevice, IMG_NULL,
+						 "Power Device");
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterPowerDevice: Failed to alloc PVRSRV_POWER_DEV"));
+		return eError;
+	}
+
+
+	psPowerDevice->pfnPrePower = pfnPrePower;
+	psPowerDevice->pfnPostPower = pfnPostPower;
+	psPowerDevice->pfnPreClockSpeedChange = pfnPreClockSpeedChange;
+	psPowerDevice->pfnPostClockSpeedChange = pfnPostClockSpeedChange;
+	psPowerDevice->hDevCookie = hDevCookie;
+	psPowerDevice->ui32DeviceIndex = ui32DeviceIndex;
+	psPowerDevice->eCurrentPowerState = eCurrentPowerState;
+	psPowerDevice->eDefaultPowerState = eDefaultPowerState;
+
+
+	List_PVRSRV_POWER_DEV_Insert(&(psSysData->psPowerDeviceList), psPowerDevice);
+
+	return (PVRSRV_OK);
+}
+
+
+PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex)
+{
+	SYS_DATA			*psSysData;
+	PVRSRV_POWER_DEV	*psPowerDev;
+
+	SysAcquireData(&psSysData);
+
+
+	psPowerDev = (PVRSRV_POWER_DEV*)
+					List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+												 MatchPowerDeviceIndex_AnyVaCb,
+												 ui32DeviceIndex);
+
+	if (psPowerDev)
+	{
+		List_PVRSRV_POWER_DEV_Remove(psPowerDev);
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_POWER_DEV), psPowerDev, IMG_NULL);
+
+	}
+
+	return (PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex)
+{
+	SYS_DATA			*psSysData;
+	PVRSRV_POWER_DEV	*psPowerDevice;
+
+	SysAcquireData(&psSysData);
+
+	if (OSIsResourceLocked(&psSysData->sPowerStateChangeResource, KERNEL_ID) ||
+		OSIsResourceLocked(&psSysData->sPowerStateChangeResource, ISR_ID))
+	{
+		return IMG_FALSE;
+	}
+
+	psPowerDevice = (PVRSRV_POWER_DEV*)
+					List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+												 MatchPowerDeviceIndex_AnyVaCb,
+												 ui32DeviceIndex);
+	return (psPowerDevice && (psPowerDevice->eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON))
+			? IMG_TRUE : IMG_FALSE;
+}
+
+
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32	ui32DeviceIndex,
+											 IMG_BOOL	bIdleDevice,
+											 IMG_VOID	*pvInfo)
+{
+	PVRSRV_ERROR		eError = PVRSRV_OK;
+	SYS_DATA			*psSysData;
+	PVRSRV_POWER_DEV	*psPowerDevice;
+
+	PVR_UNREFERENCED_PARAMETER(pvInfo);
+
+	SysAcquireData(&psSysData);
+
+	if (bIdleDevice)
+	{
+
+		eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,	"PVRSRVDevicePreClockSpeedChange : failed to acquire lock, error:0x%lx", eError));
+			return eError;
+		}
+	}
+
+
+	psPowerDevice = (PVRSRV_POWER_DEV*)
+					List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+												 MatchPowerDeviceIndex_AnyVaCb,
+												 ui32DeviceIndex);
+
+	if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange)
+	{
+			eError = psPowerDevice->pfnPreClockSpeedChange(psPowerDevice->hDevCookie,
+														   bIdleDevice,
+														   psPowerDevice->eCurrentPowerState);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+						"PVRSRVDevicePreClockSpeedChange : Device %lu failed, error:0x%lx",
+						ui32DeviceIndex, eError));
+			}
+	}
+
+	if (bIdleDevice && eError != PVRSRV_OK)
+	{
+		PVRSRVPowerUnlock(KERNEL_ID);
+	}
+
+	return eError;
+}
+
+
+IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32	ui32DeviceIndex,
+										  IMG_BOOL		bIdleDevice,
+										  IMG_VOID		*pvInfo)
+{
+	PVRSRV_ERROR		eError;
+	SYS_DATA			*psSysData;
+	PVRSRV_POWER_DEV	*psPowerDevice;
+
+	PVR_UNREFERENCED_PARAMETER(pvInfo);
+
+	SysAcquireData(&psSysData);
+
+
+	psPowerDevice = (PVRSRV_POWER_DEV*)
+					List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+												 MatchPowerDeviceIndex_AnyVaCb,
+												 ui32DeviceIndex);
+
+	if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange)
+	{
+		eError = psPowerDevice->pfnPostClockSpeedChange(psPowerDevice->hDevCookie,
+														bIdleDevice,
+														psPowerDevice->eCurrentPowerState);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					"PVRSRVDevicePostClockSpeedChange : Device %lu failed, error:0x%lx",
+					ui32DeviceIndex, eError));
+		}
+	}
+
+
+	if (bIdleDevice)
+	{
+
+		PVRSRVPowerUnlock(KERNEL_ID);
+	}
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/pvrsrv.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/pvrsrv.c
new file mode 100644
index 0000000..82cc4dd
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/pvrsrv.c
@@ -0,0 +1,1194 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "handle.h"
+#include "perproc.h"
+#include "pdump_km.h"
+#include "ra.h"
+
+#include "pvrversion.h"
+
+#include "lists.h"
+
+
+DECLARE_LIST_ANY_VA_2(BM_CONTEXT, PVRSRV_ERROR, PVRSRV_OK);
+
+DECLARE_LIST_FOR_EACH_VA(BM_HEAP);
+
+DECLARE_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_ANY_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_FOR_EACH(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_INSERT(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_REMOVE(PVRSRV_DEVICE_NODE);
+
+IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va);
+
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID)
+{
+	SYS_DEVICE_ID* psDeviceWalker;
+	SYS_DEVICE_ID* psDeviceEnd;
+
+	psDeviceWalker = &psSysData->sDeviceID[0];
+	psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
+
+
+	while (psDeviceWalker < psDeviceEnd)
+	{
+		if (!psDeviceWalker->bInUse)
+		{
+			psDeviceWalker->bInUse = IMG_TRUE;
+			*pui32DevID = psDeviceWalker->uiID;
+			return PVRSRV_OK;
+		}
+		psDeviceWalker++;
+	}
+
+	PVR_DPF((PVR_DBG_ERROR,"AllocateDeviceID: No free and valid device IDs "
+			 "available!\nPerhaps need to increase SYS_DEVICE_COUNT (in "
+			 "\"sysinfo.h\")."));
+
+
+	PVR_ASSERT(psDeviceWalker < psDeviceEnd);
+
+	return PVRSRV_ERROR_GENERIC;
+}
+
+
+PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID)
+{
+	SYS_DEVICE_ID* psDeviceWalker;
+	SYS_DEVICE_ID* psDeviceEnd;
+
+	psDeviceWalker = &psSysData->sDeviceID[0];
+	psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
+
+
+	while (psDeviceWalker < psDeviceEnd)
+	{
+
+		if	(
+				(psDeviceWalker->uiID == ui32DevID) &&
+				(psDeviceWalker->bInUse)
+			)
+		{
+			psDeviceWalker->bInUse = IMG_FALSE;
+			return PVRSRV_OK;
+		}
+		psDeviceWalker++;
+	}
+
+	PVR_DPF((PVR_DBG_ERROR,"FreeDeviceID: no matching dev ID that is in use!"));
+
+
+	PVR_ASSERT(psDeviceWalker < psDeviceEnd);
+
+	return PVRSRV_ERROR_GENERIC;
+}
+
+
+#ifndef ReadHWReg
+IMG_EXPORT
+IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+	return *(volatile IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset);
+}
+#endif
+
+
+#ifndef WriteHWReg
+IMG_EXPORT
+IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+	PVR_DPF((PVR_DBG_MESSAGE,"WriteHWReg Base:%x, Offset: %x, Value %x",pvLinRegBaseAddr,ui32Offset,ui32Value));
+
+	*(IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset) = ui32Value;
+}
+#endif
+
+
+#ifndef WriteHWRegs
+IMG_EXPORT
+IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs)
+{
+	while (ui32Count)
+	{
+		WriteHWReg (pvLinRegBaseAddr, psHWRegs->ui32RegAddr, psHWRegs->ui32RegVal);
+		psHWRegs++;
+		ui32Count--;
+	}
+}
+#endif
+
+IMG_VOID PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+	IMG_UINT *pui32DevCount;
+	PVRSRV_DEVICE_IDENTIFIER **ppsDevIdList;
+
+	pui32DevCount = va_arg(va, IMG_UINT*);
+	ppsDevIdList = va_arg(va, PVRSRV_DEVICE_IDENTIFIER**);
+
+	if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_EXT)
+	{
+		*(*ppsDevIdList) = psDeviceNode->sDevId;
+		(*ppsDevIdList)++;
+		(*pui32DevCount)++;
+	}
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
+											 	   PVRSRV_DEVICE_IDENTIFIER *psDevIdList)
+{
+	SYS_DATA			*psSysData;
+	IMG_UINT32 			i;
+
+	if (!pui32NumDevices || !psDevIdList)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDevicesKM: Invalid params"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	SysAcquireData(&psSysData);
+
+
+
+	for (i=0; i<PVRSRV_MAX_DEVICES; i++)
+	{
+		psDevIdList[i].eDeviceType = PVRSRV_DEVICE_TYPE_UNKNOWN;
+	}
+
+
+	*pui32NumDevices = 0;
+
+
+
+
+
+	List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+									   PVRSRVEnumerateDevicesKM_ForEachVaCb,
+									   pui32NumDevices,
+									   &psDevIdList);
+
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData)
+{
+	PVRSRV_ERROR	eError;
+
+
+	eError = ResManInit();
+	if (eError != PVRSRV_OK)
+	{
+		goto Error;
+	}
+
+	eError = PVRSRVPerProcessDataInit();
+	if(eError != PVRSRV_OK)
+	{
+		goto Error;
+	}
+
+
+	eError = PVRSRVHandleInit();
+	if(eError != PVRSRV_OK)
+	{
+		goto Error;
+	}
+
+
+	eError = OSCreateResource(&psSysData->sPowerStateChangeResource);
+	if (eError != PVRSRV_OK)
+	{
+		goto Error;
+	}
+
+
+	psSysData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_D0;
+	psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
+
+
+	if(OSAllocMem( PVRSRV_PAGEABLE_SELECT,
+					 sizeof(PVRSRV_EVENTOBJECT) ,
+					 (IMG_VOID **)&psSysData->psGlobalEventObject, 0,
+					 "Event Object") != PVRSRV_OK)
+	{
+
+		goto Error;
+	}
+
+	if(OSEventObjectCreate("PVRSRV_GLOBAL_EVENTOBJECT", psSysData->psGlobalEventObject) != PVRSRV_OK)
+	{
+		goto Error;
+	}
+
+	return eError;
+
+Error:
+	PVRSRVDeInit(psSysData);
+	return eError;
+}
+
+
+
+IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData)
+{
+	PVRSRV_ERROR	eError;
+
+	PVR_UNREFERENCED_PARAMETER(psSysData);
+
+	if (psSysData == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed - invalid param"));
+		return;
+	}
+
+
+	if(psSysData->psGlobalEventObject)
+	{
+		OSEventObjectDestroy(psSysData->psGlobalEventObject);
+		OSFreeMem( PVRSRV_PAGEABLE_SELECT,
+						 sizeof(PVRSRV_EVENTOBJECT),
+						 psSysData->psGlobalEventObject,
+						 0);
+		psSysData->psGlobalEventObject = IMG_NULL;
+	}
+
+	eError = PVRSRVHandleDeInit();
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed"));
+	}
+
+	eError = PVRSRVPerProcessDataDeInit();
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVPerProcessDataDeInit failed"));
+	}
+
+	ResManDeInit();
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
+											  PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*),
+											  IMG_UINT32 ui32SOCInterruptBit,
+			 								  IMG_UINT32 *pui32DeviceIndex)
+{
+	PVRSRV_ERROR		eError;
+	PVRSRV_DEVICE_NODE	*psDeviceNode;
+
+
+	if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_DEVICE_NODE),
+					 (IMG_VOID **)&psDeviceNode, IMG_NULL,
+					 "Device Node") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to alloc memory for psDeviceNode"));
+		return (PVRSRV_ERROR_OUT_OF_MEMORY);
+	}
+	OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+	eError = pfnRegisterDevice(psDeviceNode);
+	if (eError != PVRSRV_OK)
+	{
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device"));
+		return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED);
+	}
+
+
+
+
+
+
+	psDeviceNode->ui32RefCount = 1;
+	psDeviceNode->psSysData = psSysData;
+	psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit;
+
+
+	AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
+
+
+	List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+
+	*pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice (IMG_UINT32 ui32DevIndex)
+{
+	PVRSRV_DEVICE_NODE	*psDeviceNode;
+	SYS_DATA			*psSysData;
+	PVRSRV_ERROR		eError;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInitialiseDevice"));
+
+	SysAcquireData(&psSysData);
+
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE*)
+					 List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+													MatchDeviceKM_AnyVaCb,
+													ui32DevIndex,
+													IMG_TRUE);
+	if(!psDeviceNode)
+	{
+
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: requested device is not present"));
+		return PVRSRV_ERROR_INIT_FAILURE;
+	}
+	PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+
+
+
+	eError = PVRSRVResManConnect(IMG_NULL, &psDeviceNode->hResManContext);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed PVRSRVResManConnect call"));
+		return eError;
+	}
+
+
+	if(psDeviceNode->pfnInitDevice != IMG_NULL)
+	{
+		eError = psDeviceNode->pfnInitDevice(psDeviceNode);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed InitDevice call"));
+			return eError;
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_ERROR eError;
+	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+										 PVRSRV_DEV_POWER_STATE_DEFAULT,
+										 KERNEL_ID, IMG_FALSE);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
+	}
+	return eError;
+}
+
+PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_ERROR eError;
+	eError = PVRSRVDevInitCompatCheck(psDeviceNode);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVDevInitCompatCheck call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
+	}
+	return eError;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
+{
+	SYS_DATA		*psSysData;
+	PVRSRV_ERROR		eError;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem"));
+
+	SysAcquireData(&psSysData);
+
+	if (bInitSuccessful)
+	{
+		eError = SysFinalise();
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: SysFinalise failed (%d)", eError));
+			return eError;
+		}
+
+
+		eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
+														PVRSRVFinaliseSystem_SetPowerState_AnyCb);
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+
+
+		eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
+													PVRSRVFinaliseSystem_CompatCheck_AnyCb);
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+
+
+
+
+
+
+
+#if !defined(SUPPORT_PDUMP_DELAYED_INITPHASE_TERMINATION)
+	PDUMPENDINITPHASE();
+#endif
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+
+	if (psDeviceNode->pfnInitDeviceCompatCheck)
+		return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode);
+	else
+		return PVRSRV_OK;
+}
+
+IMG_VOID * PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+	PVRSRV_DEVICE_TYPE eDeviceType;
+	IMG_UINT32 ui32DevIndex;
+
+	eDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE);
+	ui32DevIndex = va_arg(va, IMG_UINT32);
+
+	if ((eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN &&
+		psDeviceNode->sDevId.eDeviceType == eDeviceType) ||
+		(eDeviceType == PVRSRV_DEVICE_TYPE_UNKNOWN &&
+		 psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex))
+	{
+		return psDeviceNode;
+	}
+	else
+	{
+		return IMG_NULL;
+	}
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32			ui32DevIndex,
+													 PVRSRV_DEVICE_TYPE	eDeviceType,
+													 IMG_HANDLE			*phDevCookie)
+{
+	PVRSRV_DEVICE_NODE	*psDeviceNode;
+	SYS_DATA			*psSysData;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM"));
+
+	SysAcquireData(&psSysData);
+
+
+	psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+												PVRSRVAcquireDeviceDataKM_Match_AnyVaCb,
+												eDeviceType,
+												ui32DevIndex);
+
+
+	if (!psDeviceNode)
+	{
+
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVAcquireDeviceDataKM: requested device is not present"));
+		return PVRSRV_ERROR_INIT_FAILURE;
+	}
+
+	PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+
+
+	if (phDevCookie)
+	{
+		*phDevCookie = (IMG_HANDLE)psDeviceNode;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex)
+{
+	PVRSRV_DEVICE_NODE	*psDeviceNode;
+	SYS_DATA			*psSysData;
+	PVRSRV_ERROR		eError;
+
+	SysAcquireData(&psSysData);
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE*)
+					 List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+													MatchDeviceKM_AnyVaCb,
+													ui32DevIndex,
+													IMG_TRUE);
+
+	if (!psDeviceNode)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: requested device %d is not present", ui32DevIndex));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+
+
+	eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex,
+										 PVRSRV_DEV_POWER_STATE_OFF,
+										 KERNEL_ID,
+										 IMG_FALSE);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVSetDevicePowerStateKM call"));
+		return eError;
+	}
+
+
+
+	eError = ResManFreeResByCriteria(psDeviceNode->hResManContext,
+									 RESMAN_CRITERIA_RESTYPE,
+									 RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+									 IMG_NULL, 0);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed ResManFreeResByCriteria call"));
+		return eError;
+	}
+
+
+
+	if(psDeviceNode->pfnDeInitDevice != IMG_NULL)
+	{
+		eError = psDeviceNode->pfnDeInitDevice(psDeviceNode);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed DeInitDevice call"));
+			return eError;
+		}
+	}
+
+
+
+	PVRSRVResManDisconnect(psDeviceNode->hResManContext, IMG_TRUE);
+	psDeviceNode->hResManContext = IMG_NULL;
+
+
+	List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
+
+
+	(IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+	OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+
+
+	return (PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PollForValueKM (volatile IMG_UINT32* pui32LinMemAddr,
+										  IMG_UINT32 ui32Value,
+										  IMG_UINT32 ui32Mask,
+										  IMG_UINT32 ui32Waitus,
+										  IMG_UINT32 ui32Tries)
+{
+	{
+		IMG_UINT32	uiMaxTime = ui32Tries * ui32Waitus;
+
+		LOOP_UNTIL_TIMEOUT(uiMaxTime)
+		{
+			if((*pui32LinMemAddr & ui32Mask) == ui32Value)
+			{
+				return PVRSRV_OK;
+			}
+			OSWaitus(ui32Waitus);
+		} END_LOOP_UNTIL_TIMEOUT();
+	}
+
+
+	return PVRSRV_ERROR_GENERIC;
+}
+
+
+#if defined (USING_ISR_INTERRUPTS)
+
+extern IMG_UINT32 gui32EventStatusServicesByISR;
+
+PVRSRV_ERROR PollForInterruptKM (IMG_UINT32 ui32Value,
+								 IMG_UINT32 ui32Mask,
+								 IMG_UINT32 ui32Waitus,
+								 IMG_UINT32 ui32Tries)
+{
+	IMG_UINT32	uiMaxTime;
+
+	uiMaxTime = ui32Tries * ui32Waitus;
+
+
+	LOOP_UNTIL_TIMEOUT(uiMaxTime)
+	{
+		if ((gui32EventStatusServicesByISR & ui32Mask) == ui32Value)
+		{
+			gui32EventStatusServicesByISR = 0;
+			return PVRSRV_OK;
+		}
+		OSWaitus(ui32Waitus);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	return PVRSRV_ERROR_GENERIC;
+}
+#endif
+
+IMG_VOID PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+	IMG_CHAR **ppszStr;
+	IMG_UINT32 *pui32StrLen;
+
+	ppszStr = va_arg(va, IMG_CHAR**);
+	pui32StrLen = va_arg(va, IMG_UINT32*);
+
+	if(psBMHeap->pImportArena)
+	{
+		RA_GetStats(psBMHeap->pImportArena,
+					ppszStr,
+					pui32StrLen);
+	}
+
+	if(psBMHeap->pVMArena)
+	{
+		RA_GetStats(psBMHeap->pVMArena,
+					ppszStr,
+					pui32StrLen);
+	}
+}
+
+PVRSRV_ERROR PVRSRVGetMiscInfoKM_BMContext_AnyVaCb(BM_CONTEXT *psBMContext, va_list va)
+{
+
+	IMG_UINT32 *pui32StrLen;
+	IMG_INT32 *pi32Count;
+	IMG_CHAR **ppszStr;
+
+	pui32StrLen = va_arg(va, IMG_UINT32*);
+	pi32Count = va_arg(va, IMG_INT32*);
+	ppszStr = va_arg(va, IMG_CHAR**);
+
+	CHECK_SPACE(*pui32StrLen);
+	*pi32Count = OSSNPrintf(*ppszStr, 100, "\nApplication Context (hDevMemContext) 0x%08X:\n",
+							(IMG_HANDLE)psBMContext);
+	UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+	List_BM_HEAP_ForEach_va(psBMContext->psBMHeap,
+							PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
+							ppszStr,
+							pui32StrLen);
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+	IMG_UINT32 *pui32StrLen;
+	IMG_INT32 *pi32Count;
+	IMG_CHAR **ppszStr;
+
+	pui32StrLen = va_arg(va, IMG_UINT32*);
+	pi32Count = va_arg(va, IMG_INT32*);
+	ppszStr = va_arg(va, IMG_CHAR**);
+
+	CHECK_SPACE(*pui32StrLen);
+	*pi32Count = OSSNPrintf(*ppszStr, 100, "\n\nDevice Type %d:\n", psDeviceNode->sDevId.eDeviceType);
+	UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+
+	if(psDeviceNode->sDevMemoryInfo.pBMKernelContext)
+	{
+		CHECK_SPACE(*pui32StrLen);
+		*pi32Count = OSSNPrintf(*ppszStr, 100, "\nKernel Context:\n");
+		UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+
+		List_BM_HEAP_ForEach_va(psDeviceNode->sDevMemoryInfo.pBMKernelContext->psBMHeap,
+								PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
+								ppszStr,
+								pui32StrLen);
+	}
+
+
+	return List_BM_CONTEXT_PVRSRV_ERROR_Any_va(psDeviceNode->sDevMemoryInfo.pBMContext,
+												PVRSRVGetMiscInfoKM_BMContext_AnyVaCb,
+							 					pui32StrLen,
+												pi32Count,
+												ppszStr);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
+{
+	SYS_DATA *psSysData;
+
+	if(!psMiscInfo)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psMiscInfo->ui32StatePresent = 0;
+
+
+	if(psMiscInfo->ui32StateRequest & ~( PVRSRV_MISC_INFO_TIMER_PRESENT
+										|PVRSRV_MISC_INFO_CLOCKGATE_PRESENT
+										|PVRSRV_MISC_INFO_MEMSTATS_PRESENT
+										|PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT
+										|PVRSRV_MISC_INFO_DDKVERSION_PRESENT
+										|PVRSRV_MISC_INFO_CPUCACHEFLUSH_PRESENT
+										|PVRSRV_MISC_INFO_RESET_PRESENT))
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	SysAcquireData(&psSysData);
+
+
+	if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) &&
+		(psSysData->pvSOCTimerRegisterKM != IMG_NULL))
+	{
+		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT;
+		psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM;
+		psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle;
+	}
+	else
+	{
+		psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL;
+		psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL;
+	}
+
+
+	if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) &&
+		(psSysData->pvSOCClockGateRegsBase != IMG_NULL))
+	{
+		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT;
+		psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase;
+		psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize;
+	}
+
+
+	if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) &&
+		(psMiscInfo->pszMemoryStr != IMG_NULL))
+	{
+		RA_ARENA			**ppArena;
+		IMG_CHAR			*pszStr;
+		IMG_UINT32			ui32StrLen;
+		IMG_INT32			i32Count;
+
+		pszStr = psMiscInfo->pszMemoryStr;
+		ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+
+		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT;
+
+
+		ppArena = &psSysData->apsLocalDevMemArena[0];
+		while(*ppArena)
+		{
+			CHECK_SPACE(ui32StrLen);
+			i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n");
+			UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+			RA_GetStats(*ppArena,
+							&pszStr,
+							&ui32StrLen);
+
+			ppArena++;
+		}
+
+
+
+		List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
+													PVRSRVGetMiscInfoKM_Device_AnyVaCb,
+													&ui32StrLen,
+													&i32Count,
+													&pszStr);
+
+
+		i32Count = OSSNPrintf(pszStr, 100, "\n\0");
+		UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+	}
+
+	if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) &&
+		(psSysData->psGlobalEventObject != IMG_NULL))
+	{
+		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT;
+		psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject;
+	}
+
+
+
+	if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL)
+		&& ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL)
+		&& (psMiscInfo->pszMemoryStr != IMG_NULL))
+	{
+		IMG_CHAR	*pszStr;
+		IMG_UINT32	ui32StrLen;
+		IMG_UINT32 	ui32LenStrPerNum = 12;
+		IMG_INT32	i32Count;
+		IMG_INT i;
+		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT;
+
+
+		psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ;
+		psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN;
+		psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BRANCH;
+		psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD;
+
+		pszStr = psMiscInfo->pszMemoryStr;
+		ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+
+		for (i=0; i<4; i++)
+		{
+			if (ui32StrLen < ui32LenStrPerNum)
+			{
+				return PVRSRV_ERROR_INVALID_PARAMS;
+			}
+
+			i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%ld", psMiscInfo->aui32DDKVersion[i]);
+			UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+			if (i != 3)
+			{
+				i32Count = OSSNPrintf(pszStr, 2, ".");
+				UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+			}
+		}
+	}
+
+#if defined(SUPPORT_CPU_CACHED_BUFFERS)
+	if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEFLUSH_PRESENT) != 0UL)
+	{
+		if(psMiscInfo->bDeferCPUCacheFlush)
+		{
+
+			if(!psMiscInfo->bCPUCacheFlushAll)
+			{
+
+
+
+				PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVGetMiscInfoKM: don't support deferred range flushes"));
+				PVR_DPF((PVR_DBG_MESSAGE,"                     using deferred flush all instead"));
+			}
+
+			psSysData->bFlushAll = IMG_TRUE;
+		}
+		else
+		{
+
+			if(psMiscInfo->bCPUCacheFlushAll)
+			{
+
+				OSFlushCPUCacheKM();
+
+				psSysData->bFlushAll = IMG_FALSE;
+			}
+			else
+			{
+
+				OSFlushCPUCacheRangeKM(psMiscInfo->pvRangeAddrStart, psMiscInfo->pvRangeAddrEnd);
+			}
+		}
+	}
+#endif
+
+#if defined(PVRSRV_RESET_ON_HWTIMEOUT)
+	if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL)
+	{
+		PVR_LOG(("User requested OS reset"));
+		OSPanic();
+	}
+#endif
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFBStatsKM(IMG_UINT32		*pui32Total,
+											 IMG_UINT32		*pui32Available)
+{
+	IMG_UINT32 ui32Total = 0, i = 0;
+	IMG_UINT32 ui32Available = 0;
+
+	*pui32Total		= 0;
+	*pui32Available = 0;
+
+
+	while(BM_ContiguousStatistics(i, &ui32Total, &ui32Available) == IMG_TRUE)
+	{
+		*pui32Total		+= ui32Total;
+		*pui32Available += ui32Available;
+
+		i++;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	SYS_DATA			*psSysData;
+	IMG_BOOL			bStatus = IMG_FALSE;
+	IMG_UINT32			ui32InterruptSource;
+
+	if(!psDeviceNode)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVDeviceLISR: Invalid params\n"));
+		goto out;
+	}
+	psSysData = psDeviceNode->psSysData;
+
+
+	ui32InterruptSource = SysGetInterruptSource(psSysData, psDeviceNode);
+	if(ui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
+	{
+		if(psDeviceNode->pfnDeviceISR != IMG_NULL)
+		{
+			bStatus = (*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData);
+		}
+
+		SysClearInterrupts(psSysData, psDeviceNode->ui32SOCInterruptBit);
+	}
+
+out:
+	return bStatus;
+}
+
+IMG_VOID PVRSRVSystemLISR_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+
+	IMG_BOOL *pbStatus;
+	IMG_UINT32 *pui32InterruptSource;
+	IMG_UINT32 *pui32ClearInterrupts;
+
+	pbStatus = va_arg(va, IMG_BOOL*);
+	pui32InterruptSource = va_arg(va, IMG_UINT32*);
+	pui32ClearInterrupts = va_arg(va, IMG_UINT32*);
+
+
+	if(psDeviceNode->pfnDeviceISR != IMG_NULL)
+	{
+		if(*pui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
+		{
+			if((*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData))
+			{
+
+				*pbStatus = IMG_TRUE;
+			}
+
+			*pui32ClearInterrupts |= psDeviceNode->ui32SOCInterruptBit;
+		}
+	}
+}
+
+IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData)
+{
+	SYS_DATA			*psSysData = pvSysData;
+	IMG_BOOL			bStatus = IMG_FALSE;
+	IMG_UINT32			ui32InterruptSource;
+	IMG_UINT32			ui32ClearInterrupts = 0;
+	if(!psSysData)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSystemLISR: Invalid params\n"));
+	}
+	else
+	{
+
+		ui32InterruptSource = SysGetInterruptSource(psSysData, IMG_NULL);
+
+
+		if(ui32InterruptSource)
+		{
+
+			List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+												PVRSRVSystemLISR_ForEachVaCb,
+												&bStatus,
+												&ui32InterruptSource,
+												&ui32ClearInterrupts);
+
+			SysClearInterrupts(psSysData, ui32ClearInterrupts);
+		}
+	}
+	return bStatus;
+}
+
+
+IMG_VOID PVRSRVMISR_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	if(psDeviceNode->pfnDeviceMISR != IMG_NULL)
+	{
+		(*psDeviceNode->pfnDeviceMISR)(psDeviceNode->pvISRData);
+	}
+}
+
+IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData)
+{
+	SYS_DATA			*psSysData = pvSysData;
+	if(!psSysData)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n"));
+		return;
+	}
+
+
+	List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+									PVRSRVMISR_ForEachCb);
+
+
+	if (PVRSRVProcessQueues(ISR_ID, IMG_FALSE) == PVRSRV_ERROR_PROCESSING_BLOCKED)
+	{
+		PVRSRVProcessQueues(ISR_ID, IMG_FALSE);
+	}
+
+
+	if (psSysData->psGlobalEventObject)
+	{
+		IMG_HANDLE hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM;
+		if(hOSEventKM)
+		{
+			OSEventObjectSignal(hOSEventKM);
+		}
+	}
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32	ui32PID)
+{
+	return PVRSRVPerProcessDataConnect(ui32PID);
+}
+
+
+IMG_EXPORT
+IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32	ui32PID)
+{
+	PVRSRVPerProcessDataDisconnect(ui32PID);
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer,
+														IMG_SIZE_T *puiBufSize, IMG_BOOL bSave)
+{
+	IMG_SIZE_T         uiBytesSaved = 0;
+	IMG_PVOID          pvLocalMemCPUVAddr;
+	RA_SEGMENT_DETAILS sSegDetails;
+
+	if (hArena == IMG_NULL)
+	{
+		return (PVRSRV_ERROR_INVALID_PARAMS);
+	}
+
+	sSegDetails.uiSize = 0;
+	sSegDetails.sCpuPhyAddr.uiAddr = 0;
+	sSegDetails.hSegment = 0;
+
+
+	while (RA_GetNextLiveSegment(hArena, &sSegDetails))
+	{
+		if (pbyBuffer == IMG_NULL)
+		{
+
+			uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
+		}
+		else
+		{
+			if ((uiBytesSaved + sizeof(sSegDetails.uiSize) + sSegDetails.uiSize) > *puiBufSize)
+			{
+				return (PVRSRV_ERROR_OUT_OF_MEMORY);
+			}
+
+			PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVSaveRestoreLiveSegments: Base %08x size %08x", sSegDetails.sCpuPhyAddr.uiAddr, sSegDetails.uiSize));
+
+
+			pvLocalMemCPUVAddr = OSMapPhysToLin(sSegDetails.sCpuPhyAddr,
+									sSegDetails.uiSize,
+									PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+									IMG_NULL);
+			if (pvLocalMemCPUVAddr == IMG_NULL)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Failed to map local memory to host"));
+				return (PVRSRV_ERROR_OUT_OF_MEMORY);
+			}
+
+			if (bSave)
+			{
+
+				OSMemCopy(pbyBuffer, &sSegDetails.uiSize, sizeof(sSegDetails.uiSize));
+				pbyBuffer += sizeof(sSegDetails.uiSize);
+
+				OSMemCopy(pbyBuffer, pvLocalMemCPUVAddr, sSegDetails.uiSize);
+				pbyBuffer += sSegDetails.uiSize;
+			}
+			else
+			{
+				IMG_UINT32 uiSize;
+
+				OSMemCopy(&uiSize, pbyBuffer, sizeof(sSegDetails.uiSize));
+
+				if (uiSize != sSegDetails.uiSize)
+				{
+					PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Segment size error"));
+				}
+				else
+				{
+					pbyBuffer += sizeof(sSegDetails.uiSize);
+
+					OSMemCopy(pvLocalMemCPUVAddr, pbyBuffer, sSegDetails.uiSize);
+					pbyBuffer += sSegDetails.uiSize;
+				}
+			}
+
+
+			uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
+
+			OSUnMapPhysToLin(pvLocalMemCPUVAddr,
+		                     sSegDetails.uiSize,
+		                     PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+		                     IMG_NULL);
+		}
+	}
+
+	if (pbyBuffer == IMG_NULL)
+	{
+		*puiBufSize = uiBytesSaved;
+	}
+
+	return (PVRSRV_OK);
+}
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/queue.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/queue.c
new file mode 100644
index 0000000..d16ab6d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/queue.c
@@ -0,0 +1,1161 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+
+#include "lists.h"
+
+DECLARE_LIST_FOR_EACH(PVRSRV_DEVICE_NODE);
+
+#if defined(__linux__) && defined(__KERNEL__)
+
+#include "proc.h"
+
+static IMG_INT
+QueuePrintCommands (PVRSRV_QUEUE_INFO * psQueue, IMG_CHAR * buffer, size_t size)
+{
+	off_t off = 0;
+	IMG_INT cmds = 0;
+	IMG_SIZE_T ui32ReadOffset  = psQueue->ui32ReadOffset;
+	IMG_SIZE_T ui32WriteOffset = psQueue->ui32WriteOffset;
+	PVRSRV_COMMAND * psCmd;
+
+	while (ui32ReadOffset != ui32WriteOffset)
+	{
+		psCmd= (PVRSRV_COMMAND *)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + ui32ReadOffset);
+
+		off = printAppend(buffer, size, off, "%p %p  %5lu  %6lu  %3lu  %5lu   %2lu   %2lu    %3lu  \n",
+							psQueue,
+					 		psCmd,
+					 		psCmd->ui32ProcessID,
+							psCmd->CommandType,
+							psCmd->ui32CmdSize,
+							psCmd->ui32DevIndex,
+							psCmd->ui32DstSyncCount,
+							psCmd->ui32SrcSyncCount,
+							psCmd->ui32DataSize);
+
+		ui32ReadOffset += psCmd->ui32CmdSize;
+		ui32ReadOffset &= psQueue->ui32QueueSize - 1;
+		cmds++;
+	}
+	if (cmds == 0)
+		off = printAppend(buffer, size, off, "%p <empty>\n", psQueue);
+	return off;
+}
+
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+void ProcSeqShowQueue(struct seq_file *sfile,void* el)
+{
+	PVRSRV_QUEUE_INFO * psQueue = (PVRSRV_QUEUE_INFO*)el;
+	IMG_INT cmds = 0;
+	IMG_SIZE_T ui32ReadOffset;
+	IMG_SIZE_T ui32WriteOffset;
+	PVRSRV_COMMAND * psCmd;
+
+	if(el == PVR_PROC_SEQ_START_TOKEN)
+	{
+		seq_printf( sfile,
+					"Command Queues\n"
+					"Queue    CmdPtr      Pid Command Size DevInd  DSC  SSC  #Data ...\n");
+		return;
+	}
+
+	ui32ReadOffset = psQueue->ui32ReadOffset;
+	ui32WriteOffset = psQueue->ui32WriteOffset;
+
+	while (ui32ReadOffset != ui32WriteOffset)
+	{
+		psCmd= (PVRSRV_COMMAND *)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + ui32ReadOffset);
+
+		seq_printf(sfile, "%p %p  %5lu  %6lu  %3lu  %5lu   %2lu   %2lu    %3lu  \n",
+							psQueue,
+					 		psCmd,
+					 		psCmd->ui32ProcessID,
+							psCmd->CommandType,
+							psCmd->ui32CmdSize,
+							psCmd->ui32DevIndex,
+							psCmd->ui32DstSyncCount,
+							psCmd->ui32SrcSyncCount,
+							psCmd->ui32DataSize);
+
+		ui32ReadOffset += psCmd->ui32CmdSize;
+		ui32ReadOffset &= psQueue->ui32QueueSize - 1;
+		cmds++;
+	}
+
+	if (cmds == 0)
+		seq_printf(sfile, "%p <empty>\n", psQueue);
+}
+
+void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off)
+{
+	PVRSRV_QUEUE_INFO * psQueue;
+	SYS_DATA * psSysData;
+
+	if(!off)
+	{
+		return PVR_PROC_SEQ_START_TOKEN;
+	}
+
+
+	SysAcquireData(&psSysData);
+
+	for (psQueue = psSysData->psQueueList; (((--off) > 0) && (psQueue != IMG_NULL)); psQueue = psQueue->psNextKM);
+	return psQueue;
+}
+
+#endif
+
+off_t
+QueuePrintQueues (IMG_CHAR * buffer, size_t size, off_t off)
+{
+	SYS_DATA * psSysData;
+	PVRSRV_QUEUE_INFO * psQueue;
+
+	SysAcquireData(&psSysData);
+
+	 if (!off)
+		  return printAppend (buffer, size, 0,
+								"Command Queues\n"
+								"Queue    CmdPtr      Pid Command Size DevInd  DSC  SSC  #Data ...\n");
+
+
+
+	for (psQueue = psSysData->psQueueList; (((--off) > 0) && (psQueue != IMG_NULL)); psQueue = psQueue->psNextKM)
+		;
+
+	return psQueue ? QueuePrintCommands (psQueue, buffer, size) : END_OF_FILE;
+}
+#endif
+
+#define GET_SPACE_IN_CMDQ(psQueue)										\
+	(((psQueue->ui32ReadOffset - psQueue->ui32WriteOffset)				\
+	+ (psQueue->ui32QueueSize - 1)) & (psQueue->ui32QueueSize - 1))
+
+#define UPDATE_QUEUE_WOFF(psQueue, ui32Size)							\
+	psQueue->ui32WriteOffset = (psQueue->ui32WriteOffset + ui32Size)	\
+	& (psQueue->ui32QueueSize - 1);
+
+#define SYNCOPS_STALE(ui32OpsComplete, ui32OpsPending)					\
+	(ui32OpsComplete >= ui32OpsPending)
+
+
+DECLARE_LIST_FOR_EACH(PVRSRV_DEVICE_NODE);
+
+static IMG_VOID QueueDumpCmdComplete(COMMAND_COMPLETE_DATA *psCmdCompleteData,
+									 IMG_UINT32				i,
+									 IMG_BOOL				bIsSrc)
+{
+	PVRSRV_SYNC_OBJECT	*psSyncObject;
+
+	psSyncObject = bIsSrc ? psCmdCompleteData->psSrcSync : psCmdCompleteData->psDstSync;
+
+	if (psCmdCompleteData->bInUse)
+	{
+		PVR_LOG(("\t%s %lu: ROC DevVAddr:0x%lX ROP:0x%lx ROC:0x%lx, WOC DevVAddr:0x%lX WOP:0x%lx WOC:0x%lx",
+				bIsSrc ? "SRC" : "DEST", i,
+				psSyncObject[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+				psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsPending,
+				psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete,
+				psSyncObject[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+				psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsPending,
+				psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete));
+	}
+	else
+	{
+		PVR_LOG(("\t%s %lu: (Not in use)", bIsSrc ? "SRC" : "DEST", i));
+	}
+}
+
+
+static IMG_VOID QueueDumpDebugInfo_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY)
+	{
+		IMG_UINT32				i;
+		SYS_DATA				*psSysData;
+		COMMAND_COMPLETE_DATA	**ppsCmdCompleteData;
+		COMMAND_COMPLETE_DATA	*psCmdCompleteData;
+
+		SysAcquireData(&psSysData);
+
+		ppsCmdCompleteData = psSysData->ppsCmdCompleteData[psDeviceNode->sDevId.ui32DeviceIndex];
+
+		if (ppsCmdCompleteData != IMG_NULL)
+		{
+			psCmdCompleteData = ppsCmdCompleteData[DC_FLIP_COMMAND];
+
+			PVR_LOG(("Command Complete Data for display device %lu:", psDeviceNode->sDevId.ui32DeviceIndex));
+
+			for (i = 0; i < psCmdCompleteData->ui32SrcSyncCount; i++)
+			{
+				QueueDumpCmdComplete(psCmdCompleteData, i, IMG_TRUE);
+			}
+
+			for (i = 0; i < psCmdCompleteData->ui32DstSyncCount; i++)
+			{
+				QueueDumpCmdComplete(psCmdCompleteData, i, IMG_FALSE);
+			}
+		}
+		else
+		{
+			PVR_LOG(("There is no Command Complete Data for display device %u", psDeviceNode->sDevId.ui32DeviceIndex));
+		}
+	}
+}
+
+
+IMG_VOID QueueDumpDebugInfo(IMG_VOID)
+{
+	SYS_DATA	*psSysData;
+	SysAcquireData(&psSysData);
+	List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList, QueueDumpDebugInfo_ForEachCb);
+}
+
+
+IMG_SIZE_T NearestPower2(IMG_SIZE_T ui32Value)
+{
+	IMG_SIZE_T ui32Temp, ui32Result = 1;
+
+	if(!ui32Value)
+		return 0;
+
+	ui32Temp = ui32Value - 1;
+	while(ui32Temp)
+	{
+		ui32Result <<= 1;
+		ui32Temp >>= 1;
+	}
+
+	return ui32Result;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
+													 PVRSRV_QUEUE_INFO **ppsQueueInfo)
+{
+	PVRSRV_QUEUE_INFO	*psQueueInfo;
+	IMG_SIZE_T			ui32Power2QueueSize = NearestPower2(ui32QueueSize);
+	SYS_DATA			*psSysData;
+	PVRSRV_ERROR		eError;
+	IMG_HANDLE			hMemBlock;
+
+	SysAcquireData(&psSysData);
+
+
+	if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_QUEUE_INFO),
+					 (IMG_VOID **)&psQueueInfo, &hMemBlock,
+					 "Queue Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Failed to alloc queue struct"));
+		goto ErrorExit;
+	}
+	OSMemSet(psQueueInfo, 0, sizeof(PVRSRV_QUEUE_INFO));
+
+	psQueueInfo->hMemBlock[0] = hMemBlock;
+	psQueueInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+
+	if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					 ui32Power2QueueSize + PVRSRV_MAX_CMD_SIZE,
+					 &psQueueInfo->pvLinQueueKM, &hMemBlock,
+					 "Command Queue") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Failed to alloc queue buffer"));
+		goto ErrorExit;
+	}
+
+	psQueueInfo->hMemBlock[1] = hMemBlock;
+	psQueueInfo->pvLinQueueUM = psQueueInfo->pvLinQueueKM;
+
+
+	PVR_ASSERT(psQueueInfo->ui32ReadOffset == 0);
+	PVR_ASSERT(psQueueInfo->ui32WriteOffset == 0);
+
+	psQueueInfo->ui32QueueSize = ui32Power2QueueSize;
+
+
+	if (psSysData->psQueueList == IMG_NULL)
+	{
+		eError = OSCreateResource(&psSysData->sQProcessResource);
+		if (eError != PVRSRV_OK)
+		{
+			goto ErrorExit;
+		}
+	}
+
+
+	if (OSLockResource(&psSysData->sQProcessResource,
+							KERNEL_ID) != PVRSRV_OK)
+	{
+		goto ErrorExit;
+	}
+
+	psQueueInfo->psNextKM = psSysData->psQueueList;
+	psSysData->psQueueList = psQueueInfo;
+
+	if (OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID) != PVRSRV_OK)
+	{
+		goto ErrorExit;
+	}
+
+	*ppsQueueInfo = psQueueInfo;
+
+	return PVRSRV_OK;
+
+ErrorExit:
+
+	if(psQueueInfo)
+	{
+		if(psQueueInfo->pvLinQueueKM)
+		{
+			OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+						psQueueInfo->ui32QueueSize,
+						psQueueInfo->pvLinQueueKM,
+						psQueueInfo->hMemBlock[1]);
+			psQueueInfo->pvLinQueueKM = IMG_NULL;
+		}
+
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					sizeof(PVRSRV_QUEUE_INFO),
+					psQueueInfo,
+					psQueueInfo->hMemBlock[0]);
+
+	}
+
+	return PVRSRV_ERROR_GENERIC;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo)
+{
+	PVRSRV_QUEUE_INFO	*psQueue;
+	SYS_DATA			*psSysData;
+	PVRSRV_ERROR		eError;
+	IMG_BOOL			bTimeout = IMG_TRUE;
+
+	SysAcquireData(&psSysData);
+
+	psQueue = psSysData->psQueueList;
+
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		if(psQueueInfo->ui32ReadOffset == psQueueInfo->ui32WriteOffset)
+		{
+			bTimeout = IMG_FALSE;
+			break;
+		}
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	if (bTimeout)
+	{
+
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyCommandQueueKM : Failed to empty queue"));
+		eError = PVRSRV_ERROR_CANNOT_FLUSH_QUEUE;
+		goto ErrorExit;
+	}
+
+
+	eError = OSLockResource(&psSysData->sQProcessResource,
+								KERNEL_ID);
+	if (eError != PVRSRV_OK)
+	{
+		goto ErrorExit;
+	}
+
+	if(psQueue == psQueueInfo)
+	{
+		psSysData->psQueueList = psQueueInfo->psNextKM;
+
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					NearestPower2(psQueueInfo->ui32QueueSize) + PVRSRV_MAX_CMD_SIZE,
+					psQueueInfo->pvLinQueueKM,
+					psQueueInfo->hMemBlock[1]);
+		psQueueInfo->pvLinQueueKM = IMG_NULL;
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					sizeof(PVRSRV_QUEUE_INFO),
+					psQueueInfo,
+					psQueueInfo->hMemBlock[0]);
+
+		psQueueInfo = IMG_NULL;
+	}
+	else
+	{
+		while(psQueue)
+		{
+			if(psQueue->psNextKM == psQueueInfo)
+			{
+				psQueue->psNextKM = psQueueInfo->psNextKM;
+
+				OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+							psQueueInfo->ui32QueueSize,
+							psQueueInfo->pvLinQueueKM,
+							psQueueInfo->hMemBlock[1]);
+				psQueueInfo->pvLinQueueKM = IMG_NULL;
+				OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+							sizeof(PVRSRV_QUEUE_INFO),
+							psQueueInfo,
+							psQueueInfo->hMemBlock[0]);
+
+				psQueueInfo = IMG_NULL;
+				break;
+			}
+			psQueue = psQueue->psNextKM;
+		}
+
+		if(!psQueue)
+		{
+			eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+			if (eError != PVRSRV_OK)
+			{
+				goto ErrorExit;
+			}
+			eError = PVRSRV_ERROR_INVALID_PARAMS;
+			goto ErrorExit;
+		}
+	}
+
+
+	eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+	if (eError != PVRSRV_OK)
+	{
+		goto ErrorExit;
+	}
+
+
+	if (psSysData->psQueueList == IMG_NULL)
+	{
+		eError = OSDestroyResource(&psSysData->sQProcessResource);
+		if (eError != PVRSRV_OK)
+		{
+			goto ErrorExit;
+		}
+	}
+
+ErrorExit:
+
+	return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
+												IMG_SIZE_T ui32ParamSize,
+												IMG_VOID **ppvSpace)
+{
+	IMG_BOOL bTimeout = IMG_TRUE;
+
+
+	ui32ParamSize =  (ui32ParamSize+3) & 0xFFFFFFFC;
+
+	if (ui32ParamSize > PVRSRV_MAX_CMD_SIZE)
+	{
+		PVR_DPF((PVR_DBG_WARNING,"PVRSRVGetQueueSpace: max command size is %d bytes", PVRSRV_MAX_CMD_SIZE));
+		return PVRSRV_ERROR_CMD_TOO_BIG;
+	}
+
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		if (GET_SPACE_IN_CMDQ(psQueue) > ui32ParamSize)
+		{
+			bTimeout = IMG_FALSE;
+			break;
+		}
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	if (bTimeout == IMG_TRUE)
+	{
+		*ppvSpace = IMG_NULL;
+
+		return PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE;
+	}
+	else
+	{
+		*ppvSpace = (IMG_VOID *)((IMG_UINTPTR_T)psQueue->pvLinQueueUM + psQueue->ui32WriteOffset);
+	}
+
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO	*psQueue,
+												PVRSRV_COMMAND		**ppsCommand,
+												IMG_UINT32			ui32DevIndex,
+												IMG_UINT16			CommandType,
+												IMG_UINT32			ui32DstSyncCount,
+												PVRSRV_KERNEL_SYNC_INFO	*apsDstSync[],
+												IMG_UINT32			ui32SrcSyncCount,
+												PVRSRV_KERNEL_SYNC_INFO	*apsSrcSync[],
+												IMG_SIZE_T			ui32DataByteSize )
+{
+	PVRSRV_ERROR 	eError;
+	PVRSRV_COMMAND	*psCommand;
+	IMG_SIZE_T		ui32CommandSize;
+	IMG_UINT32		i;
+
+
+	ui32DataByteSize = (ui32DataByteSize + 3UL) & ~3UL;
+
+
+	ui32CommandSize = sizeof(PVRSRV_COMMAND)
+					+ ((ui32DstSyncCount + ui32SrcSyncCount) * sizeof(PVRSRV_SYNC_OBJECT))
+					+ ui32DataByteSize;
+
+
+	eError = PVRSRVGetQueueSpaceKM (psQueue, ui32CommandSize, (IMG_VOID**)&psCommand);
+	if(eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	psCommand->ui32ProcessID	= OSGetCurrentProcessIDKM();
+
+
+	psCommand->ui32CmdSize		= ui32CommandSize;
+	psCommand->ui32DevIndex 	= ui32DevIndex;
+	psCommand->CommandType 		= CommandType;
+	psCommand->ui32DstSyncCount	= ui32DstSyncCount;
+	psCommand->ui32SrcSyncCount	= ui32SrcSyncCount;
+
+
+	psCommand->psDstSync		= (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand) + sizeof(PVRSRV_COMMAND));
+
+
+	psCommand->psSrcSync		= (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psDstSync)
+								+ (ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+
+	psCommand->pvData			= (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psSrcSync)
+								+ (ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+	psCommand->ui32DataSize		= ui32DataByteSize;
+
+
+	for (i=0; i<ui32DstSyncCount; i++)
+	{
+		psCommand->psDstSync[i].psKernelSyncInfoKM = apsDstSync[i];
+		psCommand->psDstSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsDstSync[i], IMG_FALSE);
+		psCommand->psDstSync[i].ui32ReadOpsPending = PVRSRVGetReadOpsPending(apsDstSync[i], IMG_FALSE);
+
+		PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Dst %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+				i, psCommand->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+				psCommand->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+				psCommand->psDstSync[i].ui32ReadOpsPending,
+				psCommand->psDstSync[i].ui32WriteOpsPending));
+	}
+
+
+	for (i=0; i<ui32SrcSyncCount; i++)
+	{
+		psCommand->psSrcSync[i].psKernelSyncInfoKM = apsSrcSync[i];
+		psCommand->psSrcSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsSrcSync[i], IMG_TRUE);
+		psCommand->psSrcSync[i].ui32ReadOpsPending = PVRSRVGetReadOpsPending(apsSrcSync[i], IMG_TRUE);
+
+		PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Src %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+				i, psCommand->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+				psCommand->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+				psCommand->psSrcSync[i].ui32ReadOpsPending,
+				psCommand->psSrcSync[i].ui32WriteOpsPending));
+	}
+
+
+	*ppsCommand = psCommand;
+
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+												PVRSRV_COMMAND *psCommand)
+{
+
+
+
+	if (psCommand->ui32DstSyncCount > 0)
+	{
+		psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+									+ psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND));
+	}
+
+	if (psCommand->ui32SrcSyncCount > 0)
+	{
+		psCommand->psSrcSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+									+ psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND)
+									+ (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+	}
+
+	psCommand->pvData = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+									+ psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND)
+									+ (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT))
+									+ (psCommand->ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+
+
+	UPDATE_QUEUE_WOFF(psQueue, psCommand->ui32CmdSize);
+
+	return PVRSRV_OK;
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVProcessCommand(SYS_DATA			*psSysData,
+								  PVRSRV_COMMAND	*psCommand,
+								  IMG_BOOL			bFlush)
+{
+	PVRSRV_SYNC_OBJECT		*psWalkerObj;
+	PVRSRV_SYNC_OBJECT		*psEndObj;
+	IMG_UINT32				i;
+	COMMAND_COMPLETE_DATA	*psCmdCompleteData;
+	PVRSRV_ERROR			eError = PVRSRV_OK;
+	IMG_UINT32				ui32WriteOpsComplete;
+	IMG_UINT32				ui32ReadOpsComplete;
+
+
+	psWalkerObj = psCommand->psDstSync;
+	psEndObj = psWalkerObj + psCommand->ui32DstSyncCount;
+	while (psWalkerObj < psEndObj)
+	{
+		PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
+
+		ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+		ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
+
+		if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
+		||	(ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending))
+		{
+			if (!bFlush ||
+				!SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
+				!SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+			{
+				return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+			}
+		}
+
+		psWalkerObj++;
+	}
+
+
+	psWalkerObj = psCommand->psSrcSync;
+	psEndObj = psWalkerObj + psCommand->ui32SrcSyncCount;
+	while (psWalkerObj < psEndObj)
+	{
+		PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
+
+		ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
+		ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+
+		if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
+		|| (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending))
+		{
+			if (!bFlush &&
+				SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) &&
+				SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+			{
+				PVR_DPF((PVR_DBG_WARNING,
+						"PVRSRVProcessCommand: Stale syncops psSyncData:0x%x ui32WriteOpsComplete:0x%x ui32WriteOpsPending:0x%x",
+						psSyncData, ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending));
+			}
+
+			if (!bFlush ||
+				!SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
+				!SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+			{
+				return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+			}
+		}
+		psWalkerObj++;
+	}
+
+
+	if (psCommand->ui32DevIndex >= SYS_DEVICE_COUNT)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+					"PVRSRVProcessCommand: invalid DeviceType 0x%x",
+					psCommand->ui32DevIndex));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+
+	psCmdCompleteData = psSysData->ppsCmdCompleteData[psCommand->ui32DevIndex][psCommand->CommandType];
+	if (psCmdCompleteData->bInUse)
+	{
+
+		return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+	}
+
+
+	psCmdCompleteData->bInUse = IMG_TRUE;
+
+
+	psCmdCompleteData->ui32DstSyncCount = psCommand->ui32DstSyncCount;
+	for (i=0; i<psCommand->ui32DstSyncCount; i++)
+	{
+		psCmdCompleteData->psDstSync[i] = psCommand->psDstSync[i];
+
+		PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Dst %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+				i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+				psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+				psCmdCompleteData->psDstSync[i].ui32ReadOpsPending,
+				psCmdCompleteData->psDstSync[i].ui32WriteOpsPending));
+	}
+
+
+	psCmdCompleteData->ui32SrcSyncCount = psCommand->ui32SrcSyncCount;
+	for (i=0; i<psCommand->ui32SrcSyncCount; i++)
+	{
+		psCmdCompleteData->psSrcSync[i] = psCommand->psSrcSync[i];
+
+		PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Src %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+				i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+				psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+				psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending,
+				psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending));
+	}
+
+
+
+
+
+
+
+
+
+
+
+	if (psSysData->ppfnCmdProcList[psCommand->ui32DevIndex][psCommand->CommandType]((IMG_HANDLE)psCmdCompleteData,
+																				psCommand->ui32DataSize,
+																				psCommand->pvData) == IMG_FALSE)
+	{
+
+
+
+		psCmdCompleteData->bInUse = IMG_FALSE;
+		eError = PVRSRV_ERROR_CMD_NOT_PROCESSED;
+	}
+
+	return eError;
+}
+
+
+IMG_VOID PVRSRVProcessQueues_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	if (psDeviceNode->bReProcessDeviceCommandComplete &&
+		psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
+	{
+		(*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
+	}
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVProcessQueues(IMG_UINT32	ui32CallerID,
+								 IMG_BOOL	bFlush)
+{
+	PVRSRV_QUEUE_INFO 	*psQueue;
+	SYS_DATA			*psSysData;
+	PVRSRV_COMMAND 		*psCommand;
+	PVRSRV_ERROR		eError;
+
+	SysAcquireData(&psSysData);
+
+
+	psSysData->bReProcessQueues = IMG_FALSE;
+
+
+	eError = OSLockResource(&psSysData->sQProcessResource,
+							ui32CallerID);
+	if(eError != PVRSRV_OK)
+	{
+
+		psSysData->bReProcessQueues = IMG_TRUE;
+
+
+		if(ui32CallerID == ISR_ID)
+		{
+			if (bFlush)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"PVRSRVProcessQueues: Couldn't acquire queue processing lock for FLUSH"));
+			}
+			else
+			{
+				PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVProcessQueues: Couldn't acquire queue processing lock"));
+			}
+		}
+		else
+		{
+			PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVProcessQueues: Queue processing lock-acquire failed when called from the Services driver."));
+			PVR_DPF((PVR_DBG_MESSAGE,"                     This is due to MISR queue processing being interrupted by the Services driver."));
+		}
+
+		return PVRSRV_OK;
+	}
+
+	psQueue = psSysData->psQueueList;
+
+	if(!psQueue)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE,"No Queues installed - cannot process commands"));
+	}
+
+	if (bFlush)
+	{
+		PVRSRVSetDCState(DC_STATE_FLUSH_COMMANDS);
+	}
+
+	while (psQueue)
+	{
+		while (psQueue->ui32ReadOffset != psQueue->ui32WriteOffset)
+		{
+			psCommand = (PVRSRV_COMMAND*)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + psQueue->ui32ReadOffset);
+
+			if (PVRSRVProcessCommand(psSysData, psCommand, bFlush) == PVRSRV_OK)
+			{
+
+				UPDATE_QUEUE_ROFF(psQueue, psCommand->ui32CmdSize)
+
+				if (bFlush)
+				{
+					continue;
+				}
+			}
+
+			break;
+		}
+		psQueue = psQueue->psNextKM;
+	}
+
+	if (bFlush)
+	{
+		PVRSRVSetDCState(DC_STATE_NO_FLUSH_COMMANDS);
+	}
+
+
+	List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+									PVRSRVProcessQueues_ForEachCb);
+
+
+
+	OSUnlockResource(&psSysData->sQProcessResource, ui32CallerID);
+
+
+	if(psSysData->bReProcessQueues)
+	{
+		return PVRSRV_ERROR_PROCESSING_BLOCKED;
+	}
+
+	return PVRSRV_OK;
+}
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+IMG_INTERNAL
+IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE	hCmdCookie,
+										   IMG_BOOL		bScheduleMISR)
+{
+	COMMAND_COMPLETE_DATA	*psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie;
+	SYS_DATA				*psSysData;
+
+	SysAcquireData(&psSysData);
+
+
+	psCmdCompleteData->bInUse = IMG_FALSE;
+
+
+	PVRSRVCommandCompleteCallbacks();
+
+#if defined(SYS_USING_INTERRUPTS)
+	if(bScheduleMISR)
+	{
+		OSScheduleMISR(psSysData);
+	}
+#else
+	PVR_UNREFERENCED_PARAMETER(bScheduleMISR);
+#endif
+}
+
+#endif
+IMG_EXPORT
+IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE	hCmdCookie,
+								 IMG_BOOL	bScheduleMISR)
+{
+	IMG_UINT32				i;
+	COMMAND_COMPLETE_DATA	*psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie;
+	SYS_DATA				*psSysData;
+
+	SysAcquireData(&psSysData);
+
+
+	for (i=0; i<psCmdCompleteData->ui32DstSyncCount; i++)
+	{
+		psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete++;
+
+		PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Dst %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+				i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+				psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+				psCmdCompleteData->psDstSync[i].ui32ReadOpsPending,
+				psCmdCompleteData->psDstSync[i].ui32WriteOpsPending));
+	}
+
+
+	for (i=0; i<psCmdCompleteData->ui32SrcSyncCount; i++)
+	{
+		psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete++;
+
+		PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Src %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+				i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+				psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+				psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending,
+				psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending));
+	}
+
+
+	psCmdCompleteData->bInUse = IMG_FALSE;
+
+
+	PVRSRVCommandCompleteCallbacks();
+
+#if defined(SYS_USING_INTERRUPTS)
+	if(bScheduleMISR)
+	{
+		OSScheduleMISR(psSysData);
+	}
+#else
+	PVR_UNREFERENCED_PARAMETER(bScheduleMISR);
+#endif
+}
+
+
+IMG_VOID PVRSRVCommandCompleteCallbacks_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	if(psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
+	{
+
+		(*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
+	}
+}
+
+IMG_VOID PVRSRVCommandCompleteCallbacks(IMG_VOID)
+{
+	SYS_DATA				*psSysData;
+	SysAcquireData(&psSysData);
+
+
+	List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+									PVRSRVCommandCompleteCallbacks_ForEachCb);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32		ui32DevIndex,
+										 PFN_CMD_PROC	*ppfnCmdProcList,
+										 IMG_UINT32		ui32MaxSyncsPerCmd[][2],
+										 IMG_UINT32		ui32CmdCount)
+{
+	SYS_DATA				*psSysData;
+	PVRSRV_ERROR			eError;
+	IMG_UINT32				i;
+	IMG_SIZE_T				ui32AllocSize;
+	PFN_CMD_PROC			*ppfnCmdProc;
+	COMMAND_COMPLETE_DATA	*psCmdCompleteData;
+
+
+	if(ui32DevIndex >= SYS_DEVICE_COUNT)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+					"PVRSRVRegisterCmdProcListKM: invalid DeviceType 0x%x",
+					ui32DevIndex));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+
+	SysAcquireData(&psSysData);
+
+
+	eError = OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 ui32CmdCount * sizeof(PFN_CMD_PROC),
+					 (IMG_VOID **)&psSysData->ppfnCmdProcList[ui32DevIndex], IMG_NULL,
+					 "Internal Queue Info structure");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc queue"));
+		return eError;
+	}
+
+
+	ppfnCmdProc = psSysData->ppfnCmdProcList[ui32DevIndex];
+
+
+	for (i=0; i<ui32CmdCount; i++)
+	{
+		ppfnCmdProc[i] = ppfnCmdProcList[i];
+	}
+
+
+	ui32AllocSize = ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA*);
+	eError = OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+					 ui32AllocSize,
+					 (IMG_VOID **)&psSysData->ppsCmdCompleteData[ui32DevIndex], IMG_NULL,
+					 "Array of Pointers for Command Store");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc CC data"));
+		goto ErrorExit;
+	}
+
+	for (i=0; i<ui32CmdCount; i++)
+	{
+
+
+		ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA)
+					  + ((ui32MaxSyncsPerCmd[i][0]
+					  +	ui32MaxSyncsPerCmd[i][1])
+					  * sizeof(PVRSRV_SYNC_OBJECT));
+
+		eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+							ui32AllocSize,
+							(IMG_VOID **)&psSysData->ppsCmdCompleteData[ui32DevIndex][i],
+							IMG_NULL,
+							"Command Complete Data");
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc cmd %d",i));
+			goto ErrorExit;
+		}
+
+
+		OSMemSet(psSysData->ppsCmdCompleteData[ui32DevIndex][i], 0x00, ui32AllocSize);
+
+		psCmdCompleteData = psSysData->ppsCmdCompleteData[ui32DevIndex][i];
+
+
+		psCmdCompleteData->psDstSync = (PVRSRV_SYNC_OBJECT*)
+										(((IMG_UINTPTR_T)psCmdCompleteData)
+										+ sizeof(COMMAND_COMPLETE_DATA));
+		psCmdCompleteData->psSrcSync = (PVRSRV_SYNC_OBJECT*)
+										(((IMG_UINTPTR_T)psCmdCompleteData->psDstSync)
+										+ (sizeof(PVRSRV_SYNC_OBJECT) * ui32MaxSyncsPerCmd[i][0]));
+
+		psCmdCompleteData->ui32AllocSize = ui32AllocSize;
+	}
+
+	return PVRSRV_OK;
+
+ErrorExit:
+
+
+
+	if(psSysData->ppsCmdCompleteData[ui32DevIndex] != IMG_NULL)
+	{
+		for (i=0; i<ui32CmdCount; i++)
+		{
+			if (psSysData->ppsCmdCompleteData[ui32DevIndex][i] != IMG_NULL)
+			{
+				ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA)
+							  + ((ui32MaxSyncsPerCmd[i][0]
+							  +	ui32MaxSyncsPerCmd[i][1])
+							  * sizeof(PVRSRV_SYNC_OBJECT));
+				OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psSysData->ppsCmdCompleteData[ui32DevIndex][i], IMG_NULL);
+				psSysData->ppsCmdCompleteData[ui32DevIndex][i] = IMG_NULL;
+			}
+		}
+		ui32AllocSize = ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA*);
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psSysData->ppsCmdCompleteData[ui32DevIndex], IMG_NULL);
+		psSysData->ppsCmdCompleteData[ui32DevIndex] = IMG_NULL;
+	}
+
+	if(psSysData->ppfnCmdProcList[ui32DevIndex] != IMG_NULL)
+	{
+		ui32AllocSize = ui32CmdCount * sizeof(PFN_CMD_PROC);
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psSysData->ppfnCmdProcList[ui32DevIndex], IMG_NULL);
+		psSysData->ppfnCmdProcList[ui32DevIndex] = IMG_NULL;
+	}
+
+	return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
+									   IMG_UINT32 ui32CmdCount)
+{
+	SYS_DATA		*psSysData;
+	IMG_UINT32		i;
+
+
+	if(ui32DevIndex >= SYS_DEVICE_COUNT)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+					"PVRSRVRemoveCmdProcListKM: invalid DeviceType 0x%x",
+					ui32DevIndex));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+
+	SysAcquireData(&psSysData);
+
+	if(psSysData->ppsCmdCompleteData[ui32DevIndex] == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveCmdProcListKM: Invalid command array"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	else
+	{
+		for(i=0; i<ui32CmdCount; i++)
+		{
+
+			if(psSysData->ppsCmdCompleteData[ui32DevIndex][i] != IMG_NULL)
+			{
+				OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+						 psSysData->ppsCmdCompleteData[ui32DevIndex][i]->ui32AllocSize,
+						 psSysData->ppsCmdCompleteData[ui32DevIndex][i],
+						 IMG_NULL);
+				psSysData->ppsCmdCompleteData[ui32DevIndex][i] = IMG_NULL;
+			}
+		}
+
+
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				 ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA*),
+				 psSysData->ppsCmdCompleteData[ui32DevIndex],
+				 IMG_NULL);
+		psSysData->ppsCmdCompleteData[ui32DevIndex] = IMG_NULL;
+	}
+
+
+	if(psSysData->ppfnCmdProcList[ui32DevIndex] != IMG_NULL)
+	{
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				 ui32CmdCount * sizeof(PFN_CMD_PROC),
+				 psSysData->ppfnCmdProcList[ui32DevIndex],
+				 IMG_NULL);
+		psSysData->ppfnCmdProcList[ui32DevIndex] = IMG_NULL;
+	}
+
+	return PVRSRV_OK;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/ra.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/ra.c
new file mode 100644
index 0000000..c2f7fb5
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/ra.c
@@ -0,0 +1,1867 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "hash.h"
+#include "ra.h"
+#include "buffer_manager.h"
+#include "osfunc.h"
+
+#ifdef __linux__
+#include <linux/kernel.h>
+#include "proc.h"
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+#include <stdio.h>
+#endif
+
+#define MINIMUM_HASH_SIZE (64)
+
+#if defined(VALIDATE_ARENA_TEST)
+
+typedef enum RESOURCE_DESCRIPTOR_TAG {
+
+	RESOURCE_SPAN_LIVE				= 10,
+	RESOURCE_SPAN_FREE,
+	IMPORTED_RESOURCE_SPAN_START,
+	IMPORTED_RESOURCE_SPAN_LIVE,
+	IMPORTED_RESOURCE_SPAN_FREE,
+	IMPORTED_RESOURCE_SPAN_END,
+
+} RESOURCE_DESCRIPTOR;
+
+typedef enum RESOURCE_TYPE_TAG {
+
+	IMPORTED_RESOURCE_TYPE		= 20,
+	NON_IMPORTED_RESOURCE_TYPE
+
+} RESOURCE_TYPE;
+
+
+static IMG_UINT32 ui32BoundaryTagID = 0;
+
+IMG_UINT32 ValidateArena(RA_ARENA *pArena);
+#endif
+
+struct _BT_
+{
+	enum bt_type
+	{
+		btt_span,
+		btt_free,
+		btt_live
+	} type;
+
+
+	IMG_UINTPTR_T base;
+	IMG_SIZE_T uSize;
+
+
+	struct _BT_ *pNextSegment;
+	struct _BT_ *pPrevSegment;
+
+	struct _BT_ *pNextFree;
+	struct _BT_ *pPrevFree;
+
+	BM_MAPPING *psMapping;
+
+#if defined(VALIDATE_ARENA_TEST)
+	RESOURCE_DESCRIPTOR eResourceSpan;
+	RESOURCE_TYPE		eResourceType;
+
+
+	IMG_UINT32			ui32BoundaryTagID;
+#endif
+
+};
+typedef struct _BT_ BT;
+
+
+struct _RA_ARENA_
+{
+
+	IMG_CHAR *name;
+
+
+	IMG_SIZE_T uQuantum;
+
+
+	IMG_BOOL (*pImportAlloc)(IMG_VOID *,
+							 IMG_SIZE_T uSize,
+							 IMG_SIZE_T *pActualSize,
+							 BM_MAPPING **ppsMapping,
+							 IMG_UINT32 uFlags,
+							 IMG_UINTPTR_T *pBase);
+	IMG_VOID (*pImportFree) (IMG_VOID *,
+						 IMG_UINTPTR_T,
+						 BM_MAPPING *psMapping);
+	IMG_VOID (*pBackingStoreFree) (IMG_VOID *, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE);
+
+
+	IMG_VOID *pImportHandle;
+
+
+#define FREE_TABLE_LIMIT 32
+
+
+	BT *aHeadFree [FREE_TABLE_LIMIT];
+
+
+	BT *pHeadSegment;
+	BT *pTailSegment;
+
+
+	HASH_TABLE *pSegmentHash;
+
+#ifdef RA_STATS
+	RA_STATISTICS sStatistics;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+#define PROC_NAME_SIZE		32
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+	struct proc_dir_entry* pProcInfo;
+	struct proc_dir_entry* pProcSegs;
+#else
+	IMG_CHAR szProcInfoName[PROC_NAME_SIZE];
+	IMG_CHAR szProcSegsName[PROC_NAME_SIZE];
+#endif
+
+	IMG_BOOL bInitProcEntry;
+#endif
+};
+#if defined(ENABLE_RA_DUMP)
+IMG_VOID RA_Dump (RA_ARENA *pArena);
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el);
+static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off);
+
+static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el);
+static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off);
+
+#else
+static IMG_INT
+RA_DumpSegs(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data);
+static IMG_INT
+RA_DumpInfo(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data);
+#endif
+
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+IMG_VOID CheckBMFreespace(IMG_VOID);
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+static IMG_CHAR *ReplaceSpaces(IMG_CHAR * const pS)
+{
+	IMG_CHAR *pT;
+
+	for(pT = pS; *pT != 0; pT++)
+	{
+		if (*pT == ' ' || *pT == '\t')
+		{
+			*pT = '_';
+		}
+	}
+
+	return pS;
+}
+#endif
+
+static IMG_BOOL
+_RequestAllocFail (IMG_VOID *_h,
+				  IMG_SIZE_T _uSize,
+				  IMG_SIZE_T *_pActualSize,
+				  BM_MAPPING **_ppsMapping,
+				  IMG_UINT32 _uFlags,
+				  IMG_UINTPTR_T *_pBase)
+{
+	PVR_UNREFERENCED_PARAMETER (_h);
+	PVR_UNREFERENCED_PARAMETER (_uSize);
+	PVR_UNREFERENCED_PARAMETER (_pActualSize);
+	PVR_UNREFERENCED_PARAMETER (_ppsMapping);
+	PVR_UNREFERENCED_PARAMETER (_uFlags);
+	PVR_UNREFERENCED_PARAMETER (_pBase);
+
+	return IMG_FALSE;
+}
+
+static IMG_UINT32
+pvr_log2 (IMG_SIZE_T n)
+{
+	IMG_UINT32 l = 0;
+	n>>=1;
+	while (n>0)
+	{
+		n>>=1;
+		l++;
+	}
+	return l;
+}
+
+static PVRSRV_ERROR
+_SegmentListInsertAfter (RA_ARENA *pArena,
+						 BT *pInsertionPoint,
+						 BT *pBT)
+{
+	PVR_ASSERT (pArena != IMG_NULL);
+	PVR_ASSERT (pInsertionPoint != IMG_NULL);
+
+	if ((pInsertionPoint == IMG_NULL) || (pArena == IMG_NULL))
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"_SegmentListInsertAfter: invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	pBT->pNextSegment = pInsertionPoint->pNextSegment;
+	pBT->pPrevSegment = pInsertionPoint;
+	if (pInsertionPoint->pNextSegment == IMG_NULL)
+		pArena->pTailSegment = pBT;
+	else
+		pInsertionPoint->pNextSegment->pPrevSegment = pBT;
+	pInsertionPoint->pNextSegment = pBT;
+
+	return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+_SegmentListInsert (RA_ARENA *pArena, BT *pBT)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+
+	if (pArena->pHeadSegment == IMG_NULL)
+	{
+		pArena->pHeadSegment = pArena->pTailSegment = pBT;
+		pBT->pNextSegment = pBT->pPrevSegment = IMG_NULL;
+	}
+	else
+	{
+		BT *pBTScan;
+
+		if (pBT->base < pArena->pHeadSegment->base)
+		{
+
+			pBT->pNextSegment = pArena->pHeadSegment;
+			pArena->pHeadSegment->pPrevSegment = pBT;
+			pArena->pHeadSegment = pBT;
+			pBT->pPrevSegment = IMG_NULL;
+		}
+		else
+		{
+
+
+
+
+			pBTScan = pArena->pHeadSegment;
+
+			while ((pBTScan->pNextSegment != IMG_NULL)  && (pBT->base >= pBTScan->pNextSegment->base))
+			{
+				pBTScan = pBTScan->pNextSegment;
+			}
+
+			eError = _SegmentListInsertAfter (pArena, pBTScan, pBT);
+			if (eError != PVRSRV_OK)
+			{
+				return eError;
+			}
+		}
+	}
+	return eError;
+}
+
+static IMG_VOID
+_SegmentListRemove (RA_ARENA *pArena, BT *pBT)
+{
+	if (pBT->pPrevSegment == IMG_NULL)
+		pArena->pHeadSegment = pBT->pNextSegment;
+	else
+		pBT->pPrevSegment->pNextSegment = pBT->pNextSegment;
+
+	if (pBT->pNextSegment == IMG_NULL)
+		pArena->pTailSegment = pBT->pPrevSegment;
+	else
+		pBT->pNextSegment->pPrevSegment = pBT->pPrevSegment;
+}
+
+static BT *
+_SegmentSplit (RA_ARENA *pArena, BT *pBT, IMG_SIZE_T uSize)
+{
+	BT *pNeighbour;
+
+	PVR_ASSERT (pArena != IMG_NULL);
+
+	if (pArena == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: invalid parameter - pArena"));
+		return IMG_NULL;
+	}
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					sizeof(BT),
+					(IMG_VOID **)&pNeighbour, IMG_NULL,
+					"Boundary Tag") != PVRSRV_OK)
+	{
+		return IMG_NULL;
+	}
+
+	OSMemSet(pNeighbour, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+	pNeighbour->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+	pNeighbour->pPrevSegment = pBT;
+	pNeighbour->pNextSegment = pBT->pNextSegment;
+	if (pBT->pNextSegment == IMG_NULL)
+		pArena->pTailSegment = pNeighbour;
+	else
+		pBT->pNextSegment->pPrevSegment = pNeighbour;
+	pBT->pNextSegment = pNeighbour;
+
+	pNeighbour->type = btt_free;
+	pNeighbour->uSize = pBT->uSize - uSize;
+	pNeighbour->base = pBT->base + uSize;
+	pNeighbour->psMapping = pBT->psMapping;
+	pBT->uSize = uSize;
+
+#if defined(VALIDATE_ARENA_TEST)
+	if (pNeighbour->pPrevSegment->eResourceType == IMPORTED_RESOURCE_TYPE)
+	{
+		pNeighbour->eResourceType = IMPORTED_RESOURCE_TYPE;
+		pNeighbour->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE;
+	}
+	else if (pNeighbour->pPrevSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+	{
+		pNeighbour->eResourceType = NON_IMPORTED_RESOURCE_TYPE;
+		pNeighbour->eResourceSpan = RESOURCE_SPAN_FREE;
+	}
+	else
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: pNeighbour->pPrevSegment->eResourceType unrecognized"));
+		PVR_DBG_BREAK;
+	}
+#endif
+
+	return pNeighbour;
+}
+
+static IMG_VOID
+_FreeListInsert (RA_ARENA *pArena, BT *pBT)
+{
+	IMG_UINT32 uIndex;
+	uIndex = pvr_log2 (pBT->uSize);
+	pBT->type = btt_free;
+	pBT->pNextFree = pArena->aHeadFree [uIndex];
+	pBT->pPrevFree = IMG_NULL;
+	if (pArena->aHeadFree[uIndex] != IMG_NULL)
+		pArena->aHeadFree[uIndex]->pPrevFree = pBT;
+	pArena->aHeadFree [uIndex] = pBT;
+}
+
+static IMG_VOID
+_FreeListRemove (RA_ARENA *pArena, BT *pBT)
+{
+	IMG_UINT32 uIndex;
+	uIndex = pvr_log2 (pBT->uSize);
+	if (pBT->pNextFree != IMG_NULL)
+		pBT->pNextFree->pPrevFree = pBT->pPrevFree;
+	if (pBT->pPrevFree == IMG_NULL)
+		pArena->aHeadFree[uIndex] = pBT->pNextFree;
+	else
+		pBT->pPrevFree->pNextFree = pBT->pNextFree;
+}
+
+static BT *
+_BuildSpanMarker (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+	BT *pBT;
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					sizeof(BT),
+					(IMG_VOID **)&pBT, IMG_NULL,
+					"Boundary Tag") != PVRSRV_OK)
+	{
+		return IMG_NULL;
+	}
+
+	OSMemSet(pBT, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+	pBT->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+	pBT->type = btt_span;
+	pBT->base = base;
+	pBT->uSize = uSize;
+	pBT->psMapping = IMG_NULL;
+
+	return pBT;
+}
+
+static BT *
+_BuildBT (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+	BT *pBT;
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					sizeof(BT),
+					(IMG_VOID **)&pBT, IMG_NULL,
+					"Boundary Tag") != PVRSRV_OK)
+	{
+		return IMG_NULL;
+	}
+
+	OSMemSet(pBT, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+	pBT->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+	pBT->type = btt_free;
+	pBT->base = base;
+	pBT->uSize = uSize;
+
+	return pBT;
+}
+
+static BT *
+_InsertResource (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+	BT *pBT;
+	PVR_ASSERT (pArena!=IMG_NULL);
+	if (pArena == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: invalid parameter - pArena"));
+		return IMG_NULL;
+	}
+
+	pBT = _BuildBT (base, uSize);
+	if (pBT != IMG_NULL)
+	{
+
+#if defined(VALIDATE_ARENA_TEST)
+		pBT->eResourceSpan = RESOURCE_SPAN_FREE;
+		pBT->eResourceType = NON_IMPORTED_RESOURCE_TYPE;
+#endif
+
+		if (_SegmentListInsert (pArena, pBT) != PVRSRV_OK)
+		{
+			PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: call to _SegmentListInsert failed"));
+			return IMG_NULL;
+		}
+		_FreeListInsert (pArena, pBT);
+#ifdef RA_STATS
+		pArena->sStatistics.uTotalResourceCount+=uSize;
+		pArena->sStatistics.uFreeResourceCount+=uSize;
+		pArena->sStatistics.uSpanCount++;
+#endif
+	}
+	return pBT;
+}
+
+static BT *
+_InsertResourceSpan (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+	PVRSRV_ERROR eError;
+	BT *pSpanStart;
+	BT *pSpanEnd;
+	BT *pBT;
+
+	PVR_ASSERT (pArena != IMG_NULL);
+	if (pArena == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"_InsertResourceSpan: invalid parameter - pArena"));
+		return IMG_NULL;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "RA_InsertResourceSpan: arena='%s', base=0x%x, size=0x%x",
+			  pArena->name, base, uSize));
+
+	pSpanStart = _BuildSpanMarker (base, uSize);
+	if (pSpanStart == IMG_NULL)
+	{
+		goto fail_start;
+	}
+
+#if defined(VALIDATE_ARENA_TEST)
+	pSpanStart->eResourceSpan = IMPORTED_RESOURCE_SPAN_START;
+	pSpanStart->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+	pSpanEnd = _BuildSpanMarker (base + uSize, 0);
+	if (pSpanEnd == IMG_NULL)
+	{
+		goto fail_end;
+	}
+
+#if defined(VALIDATE_ARENA_TEST)
+	pSpanEnd->eResourceSpan = IMPORTED_RESOURCE_SPAN_END;
+	pSpanEnd->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+	pBT = _BuildBT (base, uSize);
+	if (pBT == IMG_NULL)
+	{
+		goto fail_bt;
+	}
+
+#if defined(VALIDATE_ARENA_TEST)
+	pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE;
+	pBT->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+	eError = _SegmentListInsert (pArena, pSpanStart);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_SegListInsert;
+	}
+
+	eError = _SegmentListInsertAfter (pArena, pSpanStart, pBT);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_SegListInsert;
+	}
+
+	_FreeListInsert (pArena, pBT);
+
+	eError = _SegmentListInsertAfter (pArena, pBT, pSpanEnd);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_SegListInsert;
+	}
+
+#ifdef RA_STATS
+	pArena->sStatistics.uTotalResourceCount+=uSize;
+#endif
+	return pBT;
+
+  fail_SegListInsert:
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+
+  fail_bt:
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanEnd, IMG_NULL);
+
+  fail_end:
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanStart, IMG_NULL);
+
+  fail_start:
+	return IMG_NULL;
+}
+
+static IMG_VOID
+_FreeBT (RA_ARENA *pArena, BT *pBT, IMG_BOOL bFreeBackingStore)
+{
+	BT *pNeighbour;
+	IMG_UINTPTR_T uOrigBase;
+	IMG_SIZE_T uOrigSize;
+
+	PVR_ASSERT (pArena!=IMG_NULL);
+	PVR_ASSERT (pBT!=IMG_NULL);
+
+	if ((pArena == IMG_NULL) || (pBT == IMG_NULL))
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"_FreeBT: invalid parameter"));
+		return;
+	}
+
+#ifdef RA_STATS
+	pArena->sStatistics.uLiveSegmentCount--;
+	pArena->sStatistics.uFreeSegmentCount++;
+	pArena->sStatistics.uFreeResourceCount+=pBT->uSize;
+#endif
+
+	uOrigBase = pBT->base;
+	uOrigSize = pBT->uSize;
+
+
+	pNeighbour = pBT->pPrevSegment;
+	if (pNeighbour!=IMG_NULL
+		&& pNeighbour->type == btt_free
+		&& pNeighbour->base + pNeighbour->uSize == pBT->base)
+	{
+		_FreeListRemove (pArena, pNeighbour);
+		_SegmentListRemove (pArena, pNeighbour);
+		pBT->base = pNeighbour->base;
+		pBT->uSize += pNeighbour->uSize;
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
+
+#ifdef RA_STATS
+		pArena->sStatistics.uFreeSegmentCount--;
+#endif
+	}
+
+
+	pNeighbour = pBT->pNextSegment;
+	if (pNeighbour!=IMG_NULL
+		&& pNeighbour->type == btt_free
+		&& pBT->base + pBT->uSize == pNeighbour->base)
+	{
+		_FreeListRemove (pArena, pNeighbour);
+		_SegmentListRemove (pArena, pNeighbour);
+		pBT->uSize += pNeighbour->uSize;
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
+
+#ifdef RA_STATS
+		pArena->sStatistics.uFreeSegmentCount--;
+#endif
+	}
+
+
+	if (pArena->pBackingStoreFree != IMG_NULL && bFreeBackingStore)
+	{
+		IMG_UINTPTR_T	uRoundedStart, uRoundedEnd;
+
+
+		uRoundedStart = (uOrigBase / pArena->uQuantum) * pArena->uQuantum;
+
+		if (uRoundedStart < pBT->base)
+		{
+			uRoundedStart += pArena->uQuantum;
+		}
+
+
+		uRoundedEnd = ((uOrigBase + uOrigSize + pArena->uQuantum - 1) / pArena->uQuantum) * pArena->uQuantum;
+
+		if (uRoundedEnd > (pBT->base + pBT->uSize))
+		{
+			uRoundedEnd -= pArena->uQuantum;
+		}
+
+		if (uRoundedStart < uRoundedEnd)
+		{
+			pArena->pBackingStoreFree(pArena->pImportHandle, uRoundedStart, uRoundedEnd, (IMG_HANDLE)0);
+		}
+	}
+
+	if (pBT->pNextSegment!=IMG_NULL && pBT->pNextSegment->type == btt_span
+		&& pBT->pPrevSegment!=IMG_NULL && pBT->pPrevSegment->type == btt_span)
+	{
+		BT *next = pBT->pNextSegment;
+		BT *prev = pBT->pPrevSegment;
+		_SegmentListRemove (pArena, next);
+		_SegmentListRemove (pArena, prev);
+		_SegmentListRemove (pArena, pBT);
+		pArena->pImportFree (pArena->pImportHandle, pBT->base, pBT->psMapping);
+#ifdef RA_STATS
+		pArena->sStatistics.uSpanCount--;
+		pArena->sStatistics.uExportCount++;
+		pArena->sStatistics.uFreeSegmentCount--;
+		pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
+		pArena->sStatistics.uTotalResourceCount-=pBT->uSize;
+#endif
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), next, IMG_NULL);
+
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), prev, IMG_NULL);
+
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+
+	}
+	else
+		_FreeListInsert (pArena, pBT);
+}
+
+
+static IMG_BOOL
+_AttemptAllocAligned (RA_ARENA *pArena,
+					  IMG_SIZE_T uSize,
+					  BM_MAPPING **ppsMapping,
+					  IMG_UINT32 uFlags,
+					  IMG_UINT32 uAlignment,
+					  IMG_UINT32 uAlignmentOffset,
+					  IMG_UINTPTR_T *base)
+{
+	IMG_UINT32 uIndex;
+	PVR_ASSERT (pArena!=IMG_NULL);
+	if (pArena == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: invalid parameter - pArena"));
+		return IMG_FALSE;
+	}
+
+	if (uAlignment>1)
+		uAlignmentOffset %= uAlignment;
+
+
+
+	uIndex = pvr_log2 (uSize);
+
+#if 0
+
+	if (1u<<uIndex < uSize)
+		uIndex++;
+#endif
+
+	while (uIndex < FREE_TABLE_LIMIT && pArena->aHeadFree[uIndex]==IMG_NULL)
+		uIndex++;
+
+	while (uIndex < FREE_TABLE_LIMIT)
+	{
+		if (pArena->aHeadFree[uIndex]!=IMG_NULL)
+		{
+
+			BT *pBT;
+
+			pBT = pArena->aHeadFree [uIndex];
+			while (pBT!=IMG_NULL)
+			{
+				IMG_UINTPTR_T aligned_base;
+
+				if (uAlignment>1)
+					aligned_base = (pBT->base + uAlignmentOffset + uAlignment - 1) / uAlignment * uAlignment - uAlignmentOffset;
+				else
+					aligned_base = pBT->base;
+				PVR_DPF ((PVR_DBG_MESSAGE,
+						  "RA_AttemptAllocAligned: pBT-base=0x%x "
+						  "pBT-size=0x%x alignedbase=0x%x size=0x%x",
+						pBT->base, pBT->uSize, aligned_base, uSize));
+
+				if (pBT->base + pBT->uSize >= aligned_base + uSize)
+				{
+					if(!pBT->psMapping || pBT->psMapping->ui32Flags == uFlags)
+					{
+						_FreeListRemove (pArena, pBT);
+
+						PVR_ASSERT (pBT->type == btt_free);
+
+#ifdef RA_STATS
+						pArena->sStatistics.uLiveSegmentCount++;
+						pArena->sStatistics.uFreeSegmentCount--;
+						pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
+#endif
+
+
+						if (aligned_base > pBT->base)
+						{
+							BT *pNeighbour;
+
+							pNeighbour = _SegmentSplit (pArena, pBT, aligned_base-pBT->base);
+
+							if (pNeighbour==IMG_NULL)
+							{
+								PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Front split failed"));
+
+								_FreeListInsert (pArena, pBT);
+								return IMG_FALSE;
+							}
+
+							_FreeListInsert (pArena, pBT);
+	#ifdef RA_STATS
+							pArena->sStatistics.uFreeSegmentCount++;
+							pArena->sStatistics.uFreeResourceCount+=pBT->uSize;
+	#endif
+							pBT = pNeighbour;
+						}
+
+
+						if (pBT->uSize > uSize)
+						{
+							BT *pNeighbour;
+							pNeighbour = _SegmentSplit (pArena, pBT, uSize);
+
+							if (pNeighbour==IMG_NULL)
+							{
+								PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Back split failed"));
+
+								_FreeListInsert (pArena, pBT);
+								return IMG_FALSE;
+							}
+
+							_FreeListInsert (pArena, pNeighbour);
+	#ifdef RA_STATS
+							pArena->sStatistics.uFreeSegmentCount++;
+							pArena->sStatistics.uFreeResourceCount+=pNeighbour->uSize;
+	#endif
+						}
+
+						pBT->type = btt_live;
+
+#if defined(VALIDATE_ARENA_TEST)
+						if (pBT->eResourceType == IMPORTED_RESOURCE_TYPE)
+						{
+							pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_LIVE;
+						}
+						else if (pBT->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+						{
+							pBT->eResourceSpan = RESOURCE_SPAN_LIVE;
+						}
+						else
+						{
+							PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned ERROR: pBT->eResourceType unrecognized"));
+							PVR_DBG_BREAK;
+						}
+#endif
+						if (!HASH_Insert (pArena->pSegmentHash, pBT->base, (IMG_UINTPTR_T) pBT))
+						{
+							_FreeBT (pArena, pBT, IMG_FALSE);
+							return IMG_FALSE;
+						}
+
+						if (ppsMapping!=IMG_NULL)
+							*ppsMapping = pBT->psMapping;
+
+						*base = pBT->base;
+
+						return IMG_TRUE;
+					}
+					else
+					{
+						PVR_DPF ((PVR_DBG_MESSAGE,
+								"AttemptAllocAligned: mismatch in flags. Import has %x, request was %x", pBT->psMapping->ui32Flags, uFlags));
+
+					}
+				}
+				pBT = pBT->pNextFree;
+			}
+
+		}
+		uIndex++;
+	}
+
+	return IMG_FALSE;
+}
+
+
+
+RA_ARENA *
+RA_Create (IMG_CHAR *name,
+		   IMG_UINTPTR_T base,
+		   IMG_SIZE_T uSize,
+		   BM_MAPPING *psMapping,
+		   IMG_SIZE_T uQuantum,
+		   IMG_BOOL (*imp_alloc)(IMG_VOID *, IMG_SIZE_T uSize, IMG_SIZE_T *pActualSize,
+		                     BM_MAPPING **ppsMapping, IMG_UINT32 _flags, IMG_UINTPTR_T *pBase),
+		   IMG_VOID (*imp_free) (IMG_VOID *, IMG_UINTPTR_T, BM_MAPPING *),
+		   IMG_VOID (*backingstore_free) (IMG_VOID*, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE),
+		   IMG_VOID *pImportHandle)
+{
+	RA_ARENA *pArena;
+	BT *pBT;
+	IMG_INT i;
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "RA_Create: name='%s', base=0x%x, uSize=0x%x, alloc=0x%x, free=0x%x",
+			  name, base, uSize, imp_alloc, imp_free));
+
+
+	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof (*pArena),
+					 (IMG_VOID **)&pArena, IMG_NULL,
+					 "Resource Arena") != PVRSRV_OK)
+	{
+		goto arena_fail;
+	}
+
+	pArena->name = name;
+	pArena->pImportAlloc = (imp_alloc!=IMG_NULL) ? imp_alloc : _RequestAllocFail;
+	pArena->pImportFree = imp_free;
+	pArena->pBackingStoreFree = backingstore_free;
+	pArena->pImportHandle = pImportHandle;
+	for (i=0; i<FREE_TABLE_LIMIT; i++)
+		pArena->aHeadFree[i] = IMG_NULL;
+	pArena->pHeadSegment = IMG_NULL;
+	pArena->pTailSegment = IMG_NULL;
+	pArena->uQuantum = uQuantum;
+
+#ifdef RA_STATS
+	pArena->sStatistics.uSpanCount = 0;
+	pArena->sStatistics.uLiveSegmentCount = 0;
+	pArena->sStatistics.uFreeSegmentCount = 0;
+	pArena->sStatistics.uFreeResourceCount = 0;
+	pArena->sStatistics.uTotalResourceCount = 0;
+	pArena->sStatistics.uCumulativeAllocs = 0;
+	pArena->sStatistics.uCumulativeFrees = 0;
+	pArena->sStatistics.uImportCount = 0;
+	pArena->sStatistics.uExportCount = 0;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+	if(strcmp(pArena->name,"") != 0)
+	{
+
+#ifndef PVR_PROC_USE_SEQ_FILE
+		IMG_INT ret;
+		IMG_INT (*pfnCreateProcEntry)(const IMG_CHAR *, read_proc_t, write_proc_t, IMG_VOID *);
+
+		pArena->bInitProcEntry = !PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL);
+
+
+		pfnCreateProcEntry = pArena->bInitProcEntry ? CreateProcEntry : CreatePerProcessProcEntry;
+
+		ret = snprintf(pArena->szProcInfoName, sizeof(pArena->szProcInfoName), "ra_info_%s", pArena->name);
+		if (ret > 0 && ret < sizeof(pArena->szProcInfoName))
+		{
+			(IMG_VOID) pfnCreateProcEntry(ReplaceSpaces(pArena->szProcInfoName), RA_DumpInfo, 0, pArena);
+		}
+		else
+		{
+			pArena->szProcInfoName[0] = 0;
+			PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_info proc entry for arena %s", pArena->name));
+		}
+
+		ret = snprintf(pArena->szProcSegsName, sizeof(pArena->szProcSegsName), "ra_segs_%s", pArena->name);
+		if (ret > 0 && ret < sizeof(pArena->szProcSegsName))
+		{
+			(IMG_VOID) pfnCreateProcEntry(ReplaceSpaces(pArena->szProcSegsName), RA_DumpSegs, 0, pArena);
+		}
+		else
+		{
+			pArena->szProcSegsName[0] = 0;
+			PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_segs proc entry for arena %s", pArena->name));
+		}
+#else
+
+		IMG_INT ret;
+		IMG_CHAR szProcInfoName[PROC_NAME_SIZE];
+		IMG_CHAR szProcSegsName[PROC_NAME_SIZE];
+		struct proc_dir_entry* (*pfnCreateProcEntrySeq)(const IMG_CHAR *,
+										 IMG_VOID*,
+										 pvr_next_proc_seq_t,
+										 pvr_show_proc_seq_t,
+										 pvr_off2element_proc_seq_t,
+										 pvr_startstop_proc_seq_t,
+										 write_proc_t);
+
+		pArena->bInitProcEntry = !PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL);
+
+
+		pfnCreateProcEntrySeq = pArena->bInitProcEntry ? CreateProcEntrySeq : CreatePerProcessProcEntrySeq;
+
+		ret = snprintf(szProcInfoName, sizeof(szProcInfoName), "ra_info_%s", pArena->name);
+		if (ret > 0 && ret < sizeof(szProcInfoName))
+		{
+			pArena->pProcInfo =  pfnCreateProcEntrySeq(ReplaceSpaces(szProcInfoName), pArena, NULL,
+											 RA_ProcSeqShowInfo, RA_ProcSeqOff2ElementInfo, NULL, NULL);
+		}
+		else
+		{
+			pArena->pProcInfo = 0;
+			PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_info proc entry for arena %s", pArena->name));
+		}
+
+		ret = snprintf(szProcSegsName, sizeof(szProcSegsName), "ra_segs_%s", pArena->name);
+		if (ret > 0 && ret < sizeof(szProcInfoName))
+		{
+			pArena->pProcSegs = pfnCreateProcEntrySeq(ReplaceSpaces(szProcSegsName), pArena, NULL,
+											 RA_ProcSeqShowRegs, RA_ProcSeqOff2ElementRegs, NULL, NULL);
+		}
+		else
+		{
+			pArena->pProcSegs = 0;
+			PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_segs proc entry for arena %s", pArena->name));
+		}
+
+#endif
+
+	}
+#endif
+
+	pArena->pSegmentHash = HASH_Create (MINIMUM_HASH_SIZE);
+	if (pArena->pSegmentHash==IMG_NULL)
+	{
+		goto hash_fail;
+	}
+	if (uSize>0)
+	{
+		uSize = (uSize + uQuantum - 1) / uQuantum * uQuantum;
+		pBT = _InsertResource (pArena, base, uSize);
+		if (pBT == IMG_NULL)
+		{
+			goto insert_fail;
+		}
+		pBT->psMapping = psMapping;
+
+	}
+	return pArena;
+
+insert_fail:
+	HASH_Delete (pArena->pSegmentHash);
+hash_fail:
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
+
+arena_fail:
+	return IMG_NULL;
+}
+
+IMG_VOID
+RA_Delete (RA_ARENA *pArena)
+{
+	IMG_UINT32 uIndex;
+
+	PVR_ASSERT(pArena != IMG_NULL);
+
+	if (pArena == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: invalid parameter - pArena"));
+		return;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "RA_Delete: name='%s'", pArena->name));
+
+	for (uIndex=0; uIndex<FREE_TABLE_LIMIT; uIndex++)
+		pArena->aHeadFree[uIndex] = IMG_NULL;
+
+	while (pArena->pHeadSegment != IMG_NULL)
+	{
+		BT *pBT = pArena->pHeadSegment;
+
+		if (pBT->type != btt_free)
+		{
+			PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: allocations still exist in the arena that is being destroyed"));
+			PVR_DPF ((PVR_DBG_ERROR,"Likely Cause: client drivers not freeing alocations before destroying devmemcontext"));
+			PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: base = 0x%x size=0x%x", pBT->base, pBT->uSize));
+		}
+
+		_SegmentListRemove (pArena, pBT);
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+
+#ifdef RA_STATS
+		pArena->sStatistics.uSpanCount--;
+#endif
+	}
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+	{
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+		IMG_VOID (*pfnRemoveProcEntrySeq)(struct proc_dir_entry*);
+
+		pfnRemoveProcEntrySeq = pArena->bInitProcEntry ? RemoveProcEntrySeq : RemovePerProcessProcEntrySeq;
+
+		if (pArena->pProcInfo != 0)
+		{
+			pfnRemoveProcEntrySeq( pArena->pProcInfo );
+		}
+
+		if (pArena->pProcSegs != 0)
+		{
+			pfnRemoveProcEntrySeq( pArena->pProcSegs );
+		}
+
+#else
+		IMG_VOID (*pfnRemoveProcEntry)(const IMG_CHAR *);
+
+		pfnRemoveProcEntry = pArena->bInitProcEntry ? RemoveProcEntry : RemovePerProcessProcEntry;
+
+		if (pArena->szProcInfoName[0] != 0)
+		{
+			pfnRemoveProcEntry(pArena->szProcInfoName);
+		}
+
+		if (pArena->szProcSegsName[0] != 0)
+		{
+			pfnRemoveProcEntry(pArena->szProcSegsName);
+		}
+
+#endif
+	}
+#endif
+	HASH_Delete (pArena->pSegmentHash);
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
+
+}
+
+IMG_BOOL
+RA_TestDelete (RA_ARENA *pArena)
+{
+	PVR_ASSERT(pArena != IMG_NULL);
+
+	if (pArena != IMG_NULL)
+	{
+		while (pArena->pHeadSegment != IMG_NULL)
+		{
+			BT *pBT = pArena->pHeadSegment;
+			if (pBT->type != btt_free)
+			{
+				PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: detected resource leak!"));
+				PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: base = 0x%x size=0x%x", pBT->base, pBT->uSize));
+				return IMG_FALSE;
+			}
+		}
+	}
+
+	return IMG_TRUE;
+}
+
+IMG_BOOL
+RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+	PVR_ASSERT (pArena != IMG_NULL);
+
+	if (pArena == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"RA_Add: invalid parameter - pArena"));
+		return IMG_FALSE;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "RA_Add: name='%s', base=0x%x, size=0x%x", pArena->name, base, uSize));
+
+	uSize = (uSize + pArena->uQuantum - 1) / pArena->uQuantum * pArena->uQuantum;
+	return ((IMG_BOOL)(_InsertResource (pArena, base, uSize) != IMG_NULL));
+}
+
+IMG_BOOL
+RA_Alloc (RA_ARENA *pArena,
+		  IMG_SIZE_T uRequestSize,
+		  IMG_SIZE_T *pActualSize,
+		  BM_MAPPING **ppsMapping,
+		  IMG_UINT32 uFlags,
+		  IMG_UINT32 uAlignment,
+		  IMG_UINT32 uAlignmentOffset,
+		  IMG_UINTPTR_T *base)
+{
+	IMG_BOOL bResult;
+	IMG_SIZE_T uSize = uRequestSize;
+
+	PVR_ASSERT (pArena!=IMG_NULL);
+
+	if (pArena == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"RA_Alloc: invalid parameter - pArena"));
+		return IMG_FALSE;
+	}
+
+#if defined(VALIDATE_ARENA_TEST)
+	ValidateArena(pArena);
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+	CheckBMFreespace();
+#endif
+
+	if (pActualSize != IMG_NULL)
+	{
+		*pActualSize = uSize;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "RA_Alloc: arena='%s', size=0x%x(0x%x), alignment=0x%x, offset=0x%x",
+		   pArena->name, uSize, uRequestSize, uAlignment, uAlignmentOffset));
+
+
+
+	bResult = _AttemptAllocAligned (pArena, uSize, ppsMapping, uFlags,
+									uAlignment, uAlignmentOffset, base);
+	if (!bResult)
+	{
+		BM_MAPPING *psImportMapping;
+		IMG_UINTPTR_T import_base;
+		IMG_SIZE_T uImportSize = uSize;
+
+
+
+
+		if (uAlignment > pArena->uQuantum)
+		{
+			uImportSize += (uAlignment - 1);
+		}
+
+
+		uImportSize = ((uImportSize + pArena->uQuantum - 1)/pArena->uQuantum)*pArena->uQuantum;
+
+		bResult =
+			pArena->pImportAlloc (pArena->pImportHandle, uImportSize, &uImportSize,
+								 &psImportMapping, uFlags, &import_base);
+		if (bResult)
+		{
+			BT *pBT;
+			pBT = _InsertResourceSpan (pArena, import_base, uImportSize);
+
+			if (pBT == IMG_NULL)
+			{
+
+				pArena->pImportFree(pArena->pImportHandle, import_base,
+									psImportMapping);
+				PVR_DPF ((PVR_DBG_MESSAGE,
+						  "RA_Alloc: name='%s', size=0x%x failed!",
+						  pArena->name, uSize));
+
+				return IMG_FALSE;
+			}
+			pBT->psMapping = psImportMapping;
+#ifdef RA_STATS
+			pArena->sStatistics.uFreeSegmentCount++;
+			pArena->sStatistics.uFreeResourceCount += uImportSize;
+			pArena->sStatistics.uImportCount++;
+			pArena->sStatistics.uSpanCount++;
+#endif
+			bResult = _AttemptAllocAligned(pArena, uSize, ppsMapping, uFlags,
+										   uAlignment, uAlignmentOffset,
+										   base);
+			if (!bResult)
+			{
+				PVR_DPF ((PVR_DBG_MESSAGE,
+						  "RA_Alloc: name='%s' uAlignment failed!",
+						  pArena->name));
+			}
+		}
+	}
+#ifdef RA_STATS
+	if (bResult)
+		pArena->sStatistics.uCumulativeAllocs++;
+#endif
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "RA_Alloc: name='%s', size=0x%x, *base=0x%x = %d",
+			  pArena->name, uSize, *base, bResult));
+
+
+
+#if defined(VALIDATE_ARENA_TEST)
+	ValidateArena(pArena);
+#endif
+
+	return bResult;
+}
+
+
+#if defined(VALIDATE_ARENA_TEST)
+
+IMG_UINT32 ValidateArena(RA_ARENA *pArena)
+{
+	BT* pSegment;
+	RESOURCE_DESCRIPTOR eNextSpan;
+
+	pSegment = pArena->pHeadSegment;
+
+	if (pSegment == IMG_NULL)
+	{
+		return 0;
+	}
+
+	if (pSegment->eResourceType == IMPORTED_RESOURCE_TYPE)
+	{
+		PVR_ASSERT(pSegment->eResourceSpan == IMPORTED_RESOURCE_SPAN_START);
+
+		while (pSegment->pNextSegment)
+		{
+			eNextSpan = pSegment->pNextSegment->eResourceSpan;
+
+			switch (pSegment->eResourceSpan)
+			{
+				case IMPORTED_RESOURCE_SPAN_LIVE:
+
+					if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+						  (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
+						  (eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
+					{
+
+						PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+								pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+						PVR_DBG_BREAK;
+					}
+				break;
+
+				case IMPORTED_RESOURCE_SPAN_FREE:
+
+					if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+						  (eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
+					{
+
+						PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+								pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+						PVR_DBG_BREAK;
+					}
+				break;
+
+				case IMPORTED_RESOURCE_SPAN_END:
+
+					if ((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+						(eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
+						(eNextSpan == IMPORTED_RESOURCE_SPAN_END))
+					{
+
+						PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+								pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+						PVR_DBG_BREAK;
+					}
+				break;
+
+
+				case IMPORTED_RESOURCE_SPAN_START:
+
+					if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+						  (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE)))
+					{
+
+						PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+								pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+						PVR_DBG_BREAK;
+					}
+				break;
+
+				default:
+					PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+								pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+					PVR_DBG_BREAK;
+				break;
+			}
+			pSegment = pSegment->pNextSegment;
+		}
+	}
+	else if (pSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+	{
+		PVR_ASSERT((pSegment->eResourceSpan == RESOURCE_SPAN_FREE) || (pSegment->eResourceSpan == RESOURCE_SPAN_LIVE));
+
+		while (pSegment->pNextSegment)
+		{
+			eNextSpan = pSegment->pNextSegment->eResourceSpan;
+
+			switch (pSegment->eResourceSpan)
+			{
+				case RESOURCE_SPAN_LIVE:
+
+					if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
+						  (eNextSpan == RESOURCE_SPAN_LIVE)))
+					{
+
+						PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+								pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+						PVR_DBG_BREAK;
+					}
+				break;
+
+				case RESOURCE_SPAN_FREE:
+
+					if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
+						  (eNextSpan == RESOURCE_SPAN_LIVE)))
+					{
+
+						PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+								pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+						PVR_DBG_BREAK;
+					}
+				break;
+
+				default:
+					PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+								pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+					PVR_DBG_BREAK;
+				break;
+			}
+			pSegment = pSegment->pNextSegment;
+		}
+
+	}
+	else
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"ValidateArena ERROR: pSegment->eResourceType unrecognized"));
+
+		PVR_DBG_BREAK;
+	}
+
+	return 0;
+}
+
+#endif
+
+
+IMG_VOID
+RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore)
+{
+	BT *pBT;
+
+	PVR_ASSERT (pArena != IMG_NULL);
+
+	if (pArena == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"RA_Free: invalid parameter - pArena"));
+		return;
+	}
+
+#ifdef USE_BM_FREESPACE_CHECK
+	CheckBMFreespace();
+#endif
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "RA_Free: name='%s', base=0x%x", pArena->name, base));
+
+	pBT = (BT *) HASH_Remove (pArena->pSegmentHash, base);
+	PVR_ASSERT (pBT != IMG_NULL);
+
+	if (pBT)
+	{
+		PVR_ASSERT (pBT->base == base);
+
+#ifdef RA_STATS
+		pArena->sStatistics.uCumulativeFrees++;
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+{
+	IMG_BYTE* p;
+	IMG_BYTE* endp;
+
+	p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset();
+	endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize));
+	while ((IMG_UINT32)p & 3)
+	{
+		*p++ = 0xAA;
+	}
+	while (p < (IMG_BYTE*)((IMG_UINT32)endp & 0xfffffffc))
+	{
+		*(IMG_UINT32*)p = 0xAAAAAAAA;
+		p += sizeof(IMG_UINT32);
+	}
+	while (p < endp)
+	{
+		*p++ = 0xAA;
+	}
+	PVR_DPF((PVR_DBG_MESSAGE,"BM_FREESPACE_CHECK: RA_Free Cleared %08X to %08X (size=0x%x)",(IMG_BYTE*)pBT->base + SysGetDevicePhysOffset(),endp-1,pBT->uSize));
+}
+#endif
+		_FreeBT (pArena, pBT, bFreeBackingStore);
+	}
+}
+
+
+IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails)
+{
+	BT        *pBT;
+
+	if (psSegDetails->hSegment)
+	{
+		pBT = (BT *)psSegDetails->hSegment;
+	}
+	else
+	{
+		RA_ARENA *pArena = (RA_ARENA *)hArena;
+
+		pBT = pArena->pHeadSegment;
+	}
+
+	while (pBT != IMG_NULL)
+	{
+		if (pBT->type == btt_live)
+		{
+			psSegDetails->uiSize = pBT->uSize;
+			psSegDetails->sCpuPhyAddr.uiAddr = pBT->base;
+			psSegDetails->hSegment = (IMG_HANDLE)pBT->pNextSegment;
+
+			return IMG_TRUE;
+		}
+
+		pBT = pBT->pNextSegment;
+	}
+
+	psSegDetails->uiSize = 0;
+	psSegDetails->sCpuPhyAddr.uiAddr = 0;
+	psSegDetails->hSegment = (IMG_HANDLE)-1;
+
+	return IMG_FALSE;
+}
+
+
+#ifdef USE_BM_FREESPACE_CHECK
+RA_ARENA* pJFSavedArena = IMG_NULL;
+
+IMG_VOID CheckBMFreespace(IMG_VOID)
+{
+	BT *pBT;
+	IMG_BYTE* p;
+	IMG_BYTE* endp;
+
+	if (pJFSavedArena != IMG_NULL)
+	{
+		for (pBT=pJFSavedArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+		{
+			if (pBT->type == btt_free)
+			{
+				p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset();
+				endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize) & 0xfffffffc);
+
+				while ((IMG_UINT32)p & 3)
+				{
+					if (*p++ != 0xAA)
+					{
+						fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p);
+						for (;;);
+						break;
+					}
+				}
+				while (p < endp)
+				{
+					if (*(IMG_UINT32*)p != 0xAAAAAAAA)
+					{
+						fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p);
+						for (;;);
+						break;
+					}
+					p += 4;
+				}
+			}
+		}
+	}
+}
+#endif
+
+
+#if (defined(CONFIG_PROC_FS) && defined(DEBUG)) || defined (RA_STATS)
+static IMG_CHAR *
+_BTType (IMG_INT eType)
+{
+	switch (eType)
+	{
+	case btt_span: return "span";
+	case btt_free: return "free";
+	case btt_live: return "live";
+	}
+	return "junk";
+}
+#endif
+
+#if defined(ENABLE_RA_DUMP)
+IMG_VOID
+RA_Dump (RA_ARENA *pArena)
+{
+	BT *pBT;
+	PVR_ASSERT (pArena != IMG_NULL);
+	PVR_DPF ((PVR_DBG_MESSAGE,"Arena '%s':", pArena->name));
+	PVR_DPF ((PVR_DBG_MESSAGE,"  alloc=%08X free=%08X handle=%08X quantum=%d",
+			 pArena->pImportAlloc, pArena->pImportFree, pArena->pImportHandle,
+			 pArena->uQuantum));
+	PVR_DPF ((PVR_DBG_MESSAGE,"  segment Chain:"));
+	if (pArena->pHeadSegment != IMG_NULL &&
+	    pArena->pHeadSegment->pPrevSegment != IMG_NULL)
+		PVR_DPF ((PVR_DBG_MESSAGE,"  error: head boundary tag has invalid pPrevSegment"));
+	if (pArena->pTailSegment != IMG_NULL &&
+	    pArena->pTailSegment->pNextSegment != IMG_NULL)
+		PVR_DPF ((PVR_DBG_MESSAGE,"  error: tail boundary tag has invalid pNextSegment"));
+
+	for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+	{
+		PVR_DPF ((PVR_DBG_MESSAGE,"\tbase=0x%x size=0x%x type=%s ref=%08X",
+				 (IMG_UINT32) pBT->base, pBT->uSize, _BTType (pBT->type),
+				 pBT->pRef));
+	}
+
+#ifdef HASH_TRACE
+	HASH_Dump (pArena->pSegmentHash);
+#endif
+}
+#endif
+
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el)
+{
+	PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
+	RA_ARENA *pArena = (RA_ARENA *)handlers->data;
+	IMG_INT off = (IMG_INT)el;
+
+	switch (off)
+	{
+	case 1:
+		seq_printf(sfile, "quantum\t\t\t%lu\n", pArena->uQuantum);
+		break;
+	case 2:
+		seq_printf(sfile, "import_handle\t\t%08X\n", (IMG_UINT)pArena->pImportHandle);
+		break;
+#ifdef RA_STATS
+	case 3:
+		seq_printf(sfile,"span count\t\t%lu\n", pArena->sStatistics.uSpanCount);
+		break;
+	case 4:
+		seq_printf(sfile, "live segment count\t%lu\n", pArena->sStatistics.uLiveSegmentCount);
+		break;
+	case 5:
+		seq_printf(sfile, "free segment count\t%lu\n", pArena->sStatistics.uFreeSegmentCount);
+		break;
+	case 6:
+		seq_printf(sfile, "free resource count\t%lu (0x%x)\n",
+							pArena->sStatistics.uFreeResourceCount,
+							(IMG_UINT)pArena->sStatistics.uFreeResourceCount);
+		break;
+	case 7:
+		seq_printf(sfile, "total allocs\t\t%lu\n", pArena->sStatistics.uCumulativeAllocs);
+		break;
+	case 8:
+		seq_printf(sfile, "total frees\t\t%lu\n", pArena->sStatistics.uCumulativeFrees);
+		break;
+	case 9:
+		seq_printf(sfile, "import count\t\t%lu\n", pArena->sStatistics.uImportCount);
+		break;
+	case 10:
+		seq_printf(sfile, "export count\t\t%lu\n", pArena->sStatistics.uExportCount);
+		break;
+#endif
+	}
+
+}
+
+static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off)
+{
+#ifdef RA_STATS
+	if(off <= 9)
+#else
+	if(off <= 1)
+#endif
+		return (void*)(IMG_INT)(off+1);
+	return 0;
+}
+
+static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el)
+{
+	PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
+	RA_ARENA *pArena = (RA_ARENA *)handlers->data;
+	BT *pBT = (BT*)el;
+
+	if (el == PVR_PROC_SEQ_START_TOKEN)
+	{
+		seq_printf(sfile, "Arena \"%s\"\nBase         Size Type Ref\n", pArena->name);
+		return;
+	}
+
+	if (pBT)
+	{
+		seq_printf(sfile, "%08x %8x %4s %08x\n",
+				   (IMG_UINT)pBT->base, (IMG_UINT)pBT->uSize, _BTType (pBT->type),
+			       (IMG_UINT)pBT->psMapping);
+	}
+}
+
+static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off)
+{
+	PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
+	RA_ARENA *pArena = (RA_ARENA *)handlers->data;
+	BT *pBT = 0;
+
+	if(off == 0)
+		return PVR_PROC_SEQ_START_TOKEN;
+
+	for (pBT=pArena->pHeadSegment; --off && pBT; pBT=pBT->pNextSegment);
+
+	return (void*)pBT;
+}
+
+
+
+#else
+static IMG_INT
+RA_DumpSegs(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+	BT *pBT = 0;
+	IMG_INT len = 0;
+	RA_ARENA *pArena = (RA_ARENA *)data;
+
+	if (count < 80)
+	{
+		*start = (IMG_CHAR *)0;
+		return (0);
+	}
+	*eof = 0;
+	*start = (IMG_CHAR *)1;
+	if (off == 0)
+	{
+		return printAppend(page, count, 0, "Arena \"%s\"\nBase         Size Type Ref\n", pArena->name);
+	}
+	for (pBT=pArena->pHeadSegment; --off && pBT; pBT=pBT->pNextSegment)
+		;
+	if (pBT)
+	{
+		len = printAppend(page, count, 0, "%08x %8x %4s %08x\n",
+				 			(IMG_UINT)pBT->base, (IMG_UINT)pBT->uSize, _BTType (pBT->type),
+				 			(IMG_UINT)pBT->psMapping);
+	}
+	else
+	{
+		*eof = 1;
+	}
+	return (len);
+}
+
+static IMG_INT
+RA_DumpInfo(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+	IMG_INT len = 0;
+	RA_ARENA *pArena = (RA_ARENA *)data;
+
+	if (count < 80)
+	{
+		*start = (IMG_CHAR *)0;
+		return (0);
+	}
+	*eof = 0;
+	switch (off)
+	{
+	case 0:
+		len = printAppend(page, count, 0, "quantum\t\t\t%lu\n", pArena->uQuantum);
+		break;
+	case 1:
+		len = printAppend(page, count, 0, "import_handle\t\t%08X\n", (IMG_UINT)pArena->pImportHandle);
+		break;
+#ifdef RA_STATS
+	case 2:
+		len = printAppend(page, count, 0, "span count\t\t%lu\n", pArena->sStatistics.uSpanCount);
+		break;
+	case 3:
+		len = printAppend(page, count, 0, "live segment count\t%lu\n", pArena->sStatistics.uLiveSegmentCount);
+		break;
+	case 4:
+		len = printAppend(page, count, 0, "free segment count\t%lu\n", pArena->sStatistics.uFreeSegmentCount);
+		break;
+	case 5:
+		len = printAppend(page, count, 0, "free resource count\t%lu (0x%x)\n",
+							pArena->sStatistics.uFreeResourceCount,
+							(IMG_UINT)pArena->sStatistics.uFreeResourceCount);
+		break;
+	case 6:
+		len = printAppend(page, count, 0, "total allocs\t\t%lu\n", pArena->sStatistics.uCumulativeAllocs);
+		break;
+	case 7:
+		len = printAppend(page, count, 0, "total frees\t\t%lu\n", pArena->sStatistics.uCumulativeFrees);
+		break;
+	case 8:
+		len = printAppend(page, count, 0, "import count\t\t%lu\n", pArena->sStatistics.uImportCount);
+		break;
+	case 9:
+		len = printAppend(page, count, 0, "export count\t\t%lu\n", pArena->sStatistics.uExportCount);
+		break;
+#endif
+
+	default:
+		*eof = 1;
+	}
+	*start = (IMG_CHAR *)1;
+	return (len);
+}
+#endif
+#endif
+
+
+#ifdef RA_STATS
+PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
+							IMG_CHAR **ppszStr,
+							IMG_UINT32 *pui32StrLen)
+{
+	IMG_CHAR 	*pszStr = *ppszStr;
+	IMG_UINT32 	ui32StrLen = *pui32StrLen;
+	IMG_INT32	i32Count;
+	BT 			*pBT;
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "\nArena '%s':\n", pArena->name);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "  allocCB=%08X freeCB=%08X handle=%08X quantum=%d\n",
+							 pArena->pImportAlloc,
+							 pArena->pImportFree,
+							 pArena->pImportHandle,
+							 pArena->uQuantum);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "span count\t\t%lu\n", pArena->sStatistics.uSpanCount);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "live segment count\t%lu\n", pArena->sStatistics.uLiveSegmentCount);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "free segment count\t%lu\n", pArena->sStatistics.uFreeSegmentCount);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "free resource count\t%lu (0x%x)\n",
+							pArena->sStatistics.uFreeResourceCount,
+							(IMG_UINT)pArena->sStatistics.uFreeResourceCount);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "total allocs\t\t%lu\n", pArena->sStatistics.uCumulativeAllocs);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "total frees\t\t%lu\n", pArena->sStatistics.uCumulativeFrees);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "import count\t\t%lu\n", pArena->sStatistics.uImportCount);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "export count\t\t%lu\n", pArena->sStatistics.uExportCount);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "  segment Chain:\n");
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	if (pArena->pHeadSegment != IMG_NULL &&
+	    pArena->pHeadSegment->pPrevSegment != IMG_NULL)
+	{
+		CHECK_SPACE(ui32StrLen);
+		i32Count = OSSNPrintf(pszStr, 100, "  error: head boundary tag has invalid pPrevSegment\n");
+		UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+	}
+
+	if (pArena->pTailSegment != IMG_NULL &&
+	    pArena->pTailSegment->pNextSegment != IMG_NULL)
+	{
+		CHECK_SPACE(ui32StrLen);
+		i32Count = OSSNPrintf(pszStr, 100, "  error: tail boundary tag has invalid pNextSegment\n");
+		UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+	}
+
+	for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+	{
+		CHECK_SPACE(ui32StrLen);
+		i32Count = OSSNPrintf(pszStr, 100, "\tbase=0x%x size=0x%x type=%s ref=%08X\n",
+											 (IMG_UINT32) pBT->base,
+											 pBT->uSize,
+											 _BTType(pBT->type),
+											 pBT->psMapping);
+		UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+	}
+
+	*ppszStr = pszStr;
+	*pui32StrLen = ui32StrLen;
+
+	return PVRSRV_OK;
+}
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/resman.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/resman.c
new file mode 100644
index 0000000..14b16fe
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/common/resman.c
@@ -0,0 +1,704 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "resman.h"
+
+#ifdef __linux__
+
+#include <linux/version.h>
+#include <linux/sched.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
+#include <linux/hardirq.h>
+#else
+#include <asm/hardirq.h>
+#endif
+
+static DEFINE_MUTEX(lock);
+
+#define ACQUIRE_SYNC_OBJ  do {							\
+		if (in_interrupt()) { 							\
+			printk ("ISR cannot take RESMAN mutex\n"); 	\
+			BUG(); 										\
+		} 												\
+		else mutex_lock(&lock); 						\
+} while (0)
+#define RELEASE_SYNC_OBJ mutex_unlock(&lock)
+
+#else
+
+#define ACQUIRE_SYNC_OBJ
+#define RELEASE_SYNC_OBJ
+
+#endif
+
+#define RESMAN_SIGNATURE 0x12345678
+
+typedef struct _RESMAN_ITEM_
+{
+#ifdef DEBUG
+	IMG_UINT32				ui32Signature;
+#endif
+	struct _RESMAN_ITEM_	**ppsThis;
+	struct _RESMAN_ITEM_	*psNext;
+
+	IMG_UINT32				ui32Flags;
+	IMG_UINT32				ui32ResType;
+
+	IMG_PVOID				pvParam;
+	IMG_UINT32				ui32Param;
+
+	RESMAN_FREE_FN			pfnFreeResource;
+} RESMAN_ITEM;
+
+
+typedef struct _RESMAN_CONTEXT_
+{
+#ifdef DEBUG
+	IMG_UINT32					ui32Signature;
+#endif
+	struct	_RESMAN_CONTEXT_	**ppsThis;
+	struct	_RESMAN_CONTEXT_	*psNext;
+
+	PVRSRV_PER_PROCESS_DATA		*psPerProc;
+
+	RESMAN_ITEM					*psResItemList;
+
+} RESMAN_CONTEXT;
+
+
+typedef struct
+{
+	RESMAN_CONTEXT	*psContextList;
+
+} RESMAN_LIST, *PRESMAN_LIST;
+
+
+PRESMAN_LIST	gpsResList = IMG_NULL;
+
+#include "lists.h"
+
+static IMPLEMENT_LIST_ANY_VA(RESMAN_ITEM)
+static IMPLEMENT_LIST_ANY_VA_2(RESMAN_ITEM, IMG_BOOL, IMG_FALSE)
+static IMPLEMENT_LIST_INSERT(RESMAN_ITEM)
+static IMPLEMENT_LIST_REMOVE(RESMAN_ITEM)
+
+static IMPLEMENT_LIST_REMOVE(RESMAN_CONTEXT)
+static IMPLEMENT_LIST_INSERT(RESMAN_CONTEXT)
+
+
+#define PRINT_RESLIST(x, y, z)
+
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem, IMG_BOOL bExecuteCallback);
+
+static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT	psContext,
+										   IMG_UINT32		ui32SearchCriteria,
+										   IMG_UINT32		ui32ResType,
+										   IMG_PVOID		pvParam,
+										   IMG_UINT32		ui32Param,
+										   IMG_BOOL			bExecuteCallback);
+
+
+#ifdef DEBUG
+	static IMG_VOID ValidateResList(PRESMAN_LIST psResList);
+	#define VALIDATERESLIST() ValidateResList(gpsResList)
+#else
+	#define VALIDATERESLIST()
+#endif
+
+
+
+
+
+
+PVRSRV_ERROR ResManInit(IMG_VOID)
+{
+	if (gpsResList == IMG_NULL)
+	{
+
+		if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof(*gpsResList),
+						(IMG_VOID **)&gpsResList, IMG_NULL,
+						"Resource Manager List") != PVRSRV_OK)
+		{
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		}
+
+
+		gpsResList->psContextList = IMG_NULL;
+
+
+		VALIDATERESLIST();
+	}
+
+	return PVRSRV_OK;
+}
+
+
+IMG_VOID ResManDeInit(IMG_VOID)
+{
+	if (gpsResList != IMG_NULL)
+	{
+
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*gpsResList), gpsResList, IMG_NULL);
+		gpsResList = IMG_NULL;
+	}
+}
+
+
+PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE			hPerProc,
+								 PRESMAN_CONTEXT	*phResManContext)
+{
+	PVRSRV_ERROR	eError;
+	PRESMAN_CONTEXT	psResManContext;
+
+
+	ACQUIRE_SYNC_OBJ;
+
+
+	VALIDATERESLIST();
+
+
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psResManContext),
+						(IMG_VOID **)&psResManContext, IMG_NULL,
+						"Resource Manager Context");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVResManConnect: ERROR allocating new RESMAN context struct"));
+
+
+		VALIDATERESLIST();
+
+
+		RELEASE_SYNC_OBJ;
+
+		return eError;
+	}
+
+#ifdef DEBUG
+	psResManContext->ui32Signature = RESMAN_SIGNATURE;
+#endif
+	psResManContext->psResItemList	= IMG_NULL;
+	psResManContext->psPerProc = hPerProc;
+
+
+	List_RESMAN_CONTEXT_Insert(&gpsResList->psContextList, psResManContext);
+
+
+	VALIDATERESLIST();
+
+
+	RELEASE_SYNC_OBJ;
+
+	*phResManContext = psResManContext;
+
+	return PVRSRV_OK;
+}
+
+
+IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT psResManContext,
+								IMG_BOOL		bKernelContext)
+{
+
+	ACQUIRE_SYNC_OBJ;
+
+
+	VALIDATERESLIST();
+
+
+	PRINT_RESLIST(gpsResList, psResManContext, IMG_TRUE);
+
+
+
+	if (!bKernelContext)
+	{
+
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_OS_USERMODE_MAPPING, 0, 0, IMG_TRUE);
+
+
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_EVENT_OBJECT, 0, 0, IMG_TRUE);
+
+
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_MODIFY_SYNC_OPS, 0, 0, IMG_TRUE);
+
+
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_RENDER_CONTEXT, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_2D_CONTEXT, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC, 0, 0, IMG_TRUE);
+
+
+
+
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_DEVICE, 0, 0, IMG_TRUE);
+
+
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_BUFFERCLASS_DEVICE, 0, 0, IMG_TRUE);
+
+
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICECLASSMEM_MAPPING, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_WRAP, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_MAPPING, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_CONTEXT, 0, 0, IMG_TRUE);
+	}
+
+
+	PVR_ASSERT(psResManContext->psResItemList == IMG_NULL);
+
+
+	List_RESMAN_CONTEXT_Remove(psResManContext);
+
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_CONTEXT), psResManContext, IMG_NULL);
+
+
+
+
+	VALIDATERESLIST();
+
+
+	PRINT_RESLIST(gpsResList, psResManContext, IMG_FALSE);
+
+
+	RELEASE_SYNC_OBJ;
+}
+
+
+PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT	psResManContext,
+							   IMG_UINT32		ui32ResType,
+							   IMG_PVOID		pvParam,
+							   IMG_UINT32		ui32Param,
+							   RESMAN_FREE_FN	pfnFreeResource)
+{
+	PRESMAN_ITEM	psNewResItem;
+
+	PVR_ASSERT(psResManContext != IMG_NULL);
+	PVR_ASSERT(ui32ResType != 0);
+
+	if (psResManContext == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: invalid parameter - psResManContext"));
+		return (PRESMAN_ITEM) IMG_NULL;
+	}
+
+
+	ACQUIRE_SYNC_OBJ;
+
+
+	VALIDATERESLIST();
+
+	PVR_DPF((PVR_DBG_MESSAGE, "ResManRegisterRes: register resource "
+			"Context 0x%x, ResType 0x%x, pvParam 0x%x, ui32Param 0x%x, "
+			"FreeFunc %08X",
+			psResManContext, ui32ResType, (IMG_UINT32)pvParam,
+			ui32Param, pfnFreeResource));
+
+
+	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				   sizeof(RESMAN_ITEM), (IMG_VOID **)&psNewResItem,
+				   IMG_NULL,
+				   "Resource Manager Item") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: "
+				"ERROR allocating new resource item"));
+
+
+		RELEASE_SYNC_OBJ;
+
+		return((PRESMAN_ITEM)IMG_NULL);
+	}
+
+
+#ifdef DEBUG
+	psNewResItem->ui32Signature		= RESMAN_SIGNATURE;
+#endif
+	psNewResItem->ui32ResType		= ui32ResType;
+	psNewResItem->pvParam			= pvParam;
+	psNewResItem->ui32Param			= ui32Param;
+	psNewResItem->pfnFreeResource	= pfnFreeResource;
+	psNewResItem->ui32Flags		    = 0;
+
+
+	List_RESMAN_ITEM_Insert(&psResManContext->psResItemList, psNewResItem);
+
+
+	VALIDATERESLIST();
+
+
+	RELEASE_SYNC_OBJ;
+
+	return(psNewResItem);
+}
+
+PVRSRV_ERROR ResManFreeResByPtr(RESMAN_ITEM	*psResItem)
+{
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(psResItem != IMG_NULL);
+
+	if (psResItem == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: NULL ptr - nothing to do"));
+		return PVRSRV_OK;
+	}
+
+	PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: freeing resource at %08X", psResItem));
+
+
+	ACQUIRE_SYNC_OBJ;
+
+
+	VALIDATERESLIST();
+
+
+	eError = FreeResourceByPtr(psResItem, IMG_TRUE);
+
+
+	VALIDATERESLIST();
+
+
+	RELEASE_SYNC_OBJ;
+
+	return(eError);
+}
+
+
+PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT	psResManContext,
+									 IMG_UINT32			ui32SearchCriteria,
+									 IMG_UINT32			ui32ResType,
+									 IMG_PVOID			pvParam,
+									 IMG_UINT32			ui32Param)
+{
+	PVRSRV_ERROR	eError;
+
+	PVR_ASSERT(psResManContext != IMG_NULL);
+
+
+	ACQUIRE_SYNC_OBJ;
+
+
+	VALIDATERESLIST();
+
+	PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByCriteria: "
+			"Context 0x%x, Criteria 0x%x, Type 0x%x, Addr 0x%x, Param 0x%x",
+			psResManContext, ui32SearchCriteria, ui32ResType,
+			(IMG_UINT32)pvParam, ui32Param));
+
+
+	eError = FreeResourceByCriteria(psResManContext, ui32SearchCriteria,
+									ui32ResType, pvParam, ui32Param,
+									IMG_TRUE);
+
+
+	VALIDATERESLIST();
+
+
+	RELEASE_SYNC_OBJ;
+
+	return eError;
+}
+
+
+PVRSRV_ERROR ResManDissociateRes(RESMAN_ITEM		*psResItem,
+							 PRESMAN_CONTEXT	psNewResManContext)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	PVR_ASSERT(psResItem != IMG_NULL);
+
+	if (psResItem == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: invalid parameter - psResItem"));
+		PVR_DBG_BREAK;
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+#ifdef DEBUG
+	PVR_ASSERT(psResItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+	if (psNewResManContext != IMG_NULL)
+	{
+
+		List_RESMAN_ITEM_Remove(psResItem);
+
+
+		List_RESMAN_ITEM_Insert(&psNewResManContext->psResItemList, psResItem);
+
+	}
+	else
+	{
+		eError = FreeResourceByPtr(psResItem, IMG_FALSE);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: failed to free resource by pointer"));
+			return eError;
+		}
+	}
+
+	return eError;
+}
+
+IMG_BOOL ResManFindResourceByPtr_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+	RESMAN_ITEM		*psItem;
+
+	psItem = va_arg(va, RESMAN_ITEM*);
+
+	return (IMG_BOOL)(psCurItem == psItem);
+}
+
+
+IMG_INTERNAL PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT	psResManContext,
+												  RESMAN_ITEM		*psItem)
+{
+	PVRSRV_ERROR	eResult;
+
+	PVR_ASSERT(psResManContext != IMG_NULL);
+	PVR_ASSERT(psItem != IMG_NULL);
+
+	if ((psItem == IMG_NULL) || (psResManContext == IMG_NULL))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "ResManFindResourceByPtr: invalid parameter"));
+		PVR_DBG_BREAK;
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+#ifdef DEBUG
+	PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+
+	ACQUIRE_SYNC_OBJ;
+
+	PVR_DPF((PVR_DBG_MESSAGE,
+			"FindResourceByPtr: psItem=%08X, psItem->psNext=%08X",
+			psItem, psItem->psNext));
+
+	PVR_DPF((PVR_DBG_MESSAGE,
+			"FindResourceByPtr: Resource Ctx 0x%x, Type 0x%x, Addr 0x%x, "
+			"Param 0x%x, FnCall %08X, Flags 0x%x",
+			psResManContext,
+			psItem->ui32ResType, (IMG_UINT32)psItem->pvParam, psItem->ui32Param,
+			psItem->pfnFreeResource, psItem->ui32Flags));
+
+
+	if(List_RESMAN_ITEM_IMG_BOOL_Any_va(psResManContext->psResItemList,
+										ResManFindResourceByPtr_AnyVaCb,
+										psItem))
+	{
+		eResult = PVRSRV_OK;
+	}
+	else
+	{
+		eResult = PVRSRV_ERROR_NOT_OWNER;
+	}
+
+
+	RELEASE_SYNC_OBJ;
+
+	return eResult;
+}
+
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM	*psItem,
+									  IMG_BOOL		bExecuteCallback)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	PVR_ASSERT(psItem != IMG_NULL);
+
+	if (psItem == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: invalid parameter"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+#ifdef DEBUG
+	PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+	PVR_DPF((PVR_DBG_MESSAGE,
+			"FreeResourceByPtr: psItem=%08X, psItem->psNext=%08X",
+			psItem, psItem->psNext));
+
+	PVR_DPF((PVR_DBG_MESSAGE,
+			"FreeResourceByPtr: Type 0x%x, Addr 0x%x, "
+			"Param 0x%x, FnCall %08X, Flags 0x%x",
+			psItem->ui32ResType, (IMG_UINT32)psItem->pvParam, psItem->ui32Param,
+			psItem->pfnFreeResource, psItem->ui32Flags));
+
+
+	List_RESMAN_ITEM_Remove(psItem);
+
+
+
+	RELEASE_SYNC_OBJ;
+
+
+	if (bExecuteCallback)
+	{
+		eError = psItem->pfnFreeResource(psItem->pvParam, psItem->ui32Param);
+	 	if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR calling FreeResource function"));
+		}
+	}
+
+
+	ACQUIRE_SYNC_OBJ;
+
+
+	if(OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_ITEM), psItem, IMG_NULL) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR freeing resource list item memory"));
+		eError = PVRSRV_ERROR_GENERIC;
+	}
+
+	return(eError);
+}
+
+IMG_VOID* FreeResourceByCriteria_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+	IMG_UINT32 ui32SearchCriteria;
+	IMG_UINT32 ui32ResType;
+	IMG_PVOID pvParam;
+	IMG_UINT32 ui32Param;
+
+	ui32SearchCriteria = va_arg(va, IMG_UINT32);
+	ui32ResType = va_arg(va, IMG_UINT32);
+	pvParam = va_arg(va, IMG_PVOID);
+	ui32Param = va_arg(va, IMG_UINT32);
+
+
+	if(
+
+		(((ui32SearchCriteria & RESMAN_CRITERIA_RESTYPE) == 0UL) ||
+		(psCurItem->ui32ResType == ui32ResType))
+	&&
+
+		(((ui32SearchCriteria & RESMAN_CRITERIA_PVOID_PARAM) == 0UL) ||
+			 (psCurItem->pvParam == pvParam))
+	&&
+
+		(((ui32SearchCriteria & RESMAN_CRITERIA_UI32_PARAM) == 0UL) ||
+			 (psCurItem->ui32Param == ui32Param))
+		)
+	{
+		return psCurItem;
+	}
+	else
+	{
+		return IMG_NULL;
+	}
+}
+
+static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT	psResManContext,
+										   IMG_UINT32		ui32SearchCriteria,
+										   IMG_UINT32		ui32ResType,
+										   IMG_PVOID		pvParam,
+										   IMG_UINT32		ui32Param,
+										   IMG_BOOL			bExecuteCallback)
+{
+	PRESMAN_ITEM	psCurItem;
+	PVRSRV_ERROR	eError = PVRSRV_OK;
+
+
+
+	while((psCurItem = (PRESMAN_ITEM)
+				List_RESMAN_ITEM_Any_va(psResManContext->psResItemList,
+										FreeResourceByCriteria_AnyVaCb,
+										ui32SearchCriteria,
+										ui32ResType,
+						 				pvParam,
+						 				ui32Param)) != IMG_NULL
+		  	&& eError == PVRSRV_OK)
+	{
+		eError = FreeResourceByPtr(psCurItem, bExecuteCallback);
+	}
+
+	return eError;
+}
+
+
+#ifdef DEBUG
+static IMG_VOID ValidateResList(PRESMAN_LIST psResList)
+{
+	PRESMAN_ITEM	psCurItem, *ppsThisItem;
+	PRESMAN_CONTEXT	psCurContext, *ppsThisContext;
+
+
+	if (psResList == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "ValidateResList: resman not initialised yet"));
+		return;
+	}
+
+	psCurContext = psResList->psContextList;
+	ppsThisContext = &psResList->psContextList;
+
+
+	while(psCurContext != IMG_NULL)
+	{
+
+		PVR_ASSERT(psCurContext->ui32Signature == RESMAN_SIGNATURE);
+		if (psCurContext->ppsThis != ppsThisContext)
+		{
+			PVR_DPF((PVR_DBG_WARNING,
+					"psCC=%08X psCC->ppsThis=%08X psCC->psNext=%08X ppsTC=%08X",
+					psCurContext, psCurContext->ppsThis,
+					psCurContext->psNext, ppsThisContext));
+			PVR_ASSERT(psCurContext->ppsThis == ppsThisContext);
+		}
+
+
+		psCurItem = psCurContext->psResItemList;
+		ppsThisItem = &psCurContext->psResItemList;
+		while(psCurItem != IMG_NULL)
+		{
+
+			PVR_ASSERT(psCurItem->ui32Signature == RESMAN_SIGNATURE);
+			if (psCurItem->ppsThis != ppsThisItem)
+			{
+				PVR_DPF((PVR_DBG_WARNING,
+						"psCurItem=%08X psCurItem->ppsThis=%08X psCurItem->psNext=%08X ppsThisItem=%08X",
+						psCurItem, psCurItem->ppsThis, psCurItem->psNext, ppsThisItem));
+				PVR_ASSERT(psCurItem->ppsThis == ppsThisItem);
+			}
+
+
+			ppsThisItem = &psCurItem->psNext;
+			psCurItem = psCurItem->psNext;
+		}
+
+
+		ppsThisContext = &psCurContext->psNext;
+		psCurContext = psCurContext->psNext;
+	}
+}
+#endif
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.c
new file mode 100644
index 0000000..ad24b6f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.c
@@ -0,0 +1,2772 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "hash.h"
+#include "ra.h"
+#include "pdump_km.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "mmu.h"
+#include "sgxconfig.h"
+
+#define UINT32_MAX_VALUE	0xFFFFFFFFUL
+
+#define SGX_MAX_PD_ENTRIES	(1<<(SGX_FEATURE_ADDRESS_SPACE_SIZE - SGX_MMU_PT_SHIFT - SGX_MMU_PAGE_SHIFT))
+
+typedef struct _MMU_PT_INFO_
+{
+
+	IMG_VOID *hPTPageOSMemHandle;
+	IMG_CPU_VIRTADDR PTPageCpuVAddr;
+	IMG_UINT32 ui32ValidPTECount;
+} MMU_PT_INFO;
+
+struct _MMU_CONTEXT_
+{
+
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+
+	IMG_CPU_VIRTADDR pvPDCpuVAddr;
+	IMG_DEV_PHYADDR sPDDevPAddr;
+
+	IMG_VOID *hPDOSMemHandle;
+
+
+	MMU_PT_INFO *apsPTInfoList[SGX_MAX_PD_ENTRIES];
+
+	PVRSRV_SGXDEV_INFO *psDevInfo;
+
+#if defined(PDUMP)
+	IMG_UINT32 ui32PDumpMMUContextID;
+#endif
+
+	struct _MMU_CONTEXT_ *psNext;
+};
+
+struct _MMU_HEAP_
+{
+
+	MMU_CONTEXT			*psMMUContext;
+
+
+
+
+	IMG_UINT32			ui32PDBaseIndex;
+
+	IMG_UINT32			ui32PageTableCount;
+
+	IMG_UINT32			ui32PTETotal;
+
+	IMG_UINT32			ui32PDEPageSizeCtrl;
+
+
+
+
+	IMG_UINT32			ui32DataPageSize;
+
+	IMG_UINT32			ui32DataPageBitWidth;
+
+	IMG_UINT32			ui32DataPageMask;
+
+
+
+
+	IMG_UINT32			ui32PTShift;
+
+	IMG_UINT32			ui32PTBitWidth;
+
+	IMG_UINT32			ui32PTMask;
+
+	IMG_UINT32			ui32PTSize;
+
+	IMG_UINT32			ui32PTECount;
+
+
+
+
+	IMG_UINT32			ui32PDShift;
+
+	IMG_UINT32			ui32PDBitWidth;
+
+	IMG_UINT32			ui32PDMask;
+
+
+
+	RA_ARENA *psVMArena;
+	DEV_ARENA_DESCRIPTOR *psDevArena;
+};
+
+
+
+#if defined (SUPPORT_SGX_MMU_DUMMY_PAGE)
+#define DUMMY_DATA_PAGE_SIGNATURE	0xDEADBEEF
+#endif
+
+#if defined(PDUMP)
+static IMG_VOID
+MMU_PDumpPageTables	(MMU_HEAP *pMMUHeap,
+					 IMG_DEV_VIRTADDR DevVAddr,
+					 IMG_SIZE_T uSize,
+					 IMG_BOOL bForUnmap,
+					 IMG_HANDLE hUniqueTag);
+#endif
+
+#define PAGE_TEST					0
+#if PAGE_TEST
+static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr);
+#endif
+
+#define PT_DEBUG 0
+#if PT_DEBUG
+static IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
+{
+	IMG_UINT32 *p = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr;
+	IMG_UINT32 i;
+
+
+	for(i = 0; i < 1024; i += 8)
+	{
+		PVR_DPF((PVR_DBG_WARNING,
+				 "%.8lx %.8lx %.8lx %.8lx %.8lx %.8lx %.8lx %.8lx\n",
+				 p[i + 0], p[i + 1], p[i + 2], p[i + 3],
+				 p[i + 4], p[i + 5], p[i + 6], p[i + 7]));
+	}
+}
+
+static IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
+{
+	IMG_UINT32 *p = (IMG_UINT32*) psPTInfoList->PTPageCpuVAddr;
+	IMG_UINT32 i, ui32Count = 0;
+
+
+	for(i = 0; i < 1024; i++)
+		if(p[i] & SGX_MMU_PTE_VALID)
+			ui32Count++;
+
+	if(psPTInfoList->ui32ValidPTECount != ui32Count)
+	{
+		PVR_DPF((PVR_DBG_WARNING, "ui32ValidPTECount: %lu ui32Count: %lu\n",
+				 psPTInfoList->ui32ValidPTECount, ui32Count));
+		DumpPT(psPTInfoList);
+		BUG();
+	}
+}
+#else
+static INLINE IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
+{
+	PVR_UNREFERENCED_PARAMETER(psPTInfoList);
+}
+
+static INLINE IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
+{
+	PVR_UNREFERENCED_PARAMETER(psPTInfoList);
+}
+#endif
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+IMG_VOID
+EnableHostAccess (MMU_CONTEXT *psMMUContext)
+{
+	IMG_UINT32 ui32RegVal;
+	IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM;
+
+
+
+
+	ui32RegVal = OSReadHWReg(pvRegsBaseKM, EUR_CR_BIF_CTRL);
+
+	OSWriteHWReg(pvRegsBaseKM,
+				EUR_CR_BIF_CTRL,
+				ui32RegVal | EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+
+	PDUMPREG(EUR_CR_BIF_CTRL, EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+}
+
+IMG_VOID
+DisableHostAccess (MMU_CONTEXT *psMMUContext)
+{
+	IMG_UINT32 ui32RegVal;
+	IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM;
+
+
+
+
+
+	OSWriteHWReg(pvRegsBaseKM,
+				EUR_CR_BIF_CTRL,
+				ui32RegVal & ~EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+
+	PDUMPREG(EUR_CR_BIF_CTRL, 0);
+}
+#endif
+
+
+IMG_VOID MMU_InvalidateSystemLevelCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+	#if defined(SGX_FEATURE_MP)
+	psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_SL;
+	#else
+
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+	#endif
+}
+
+
+IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+	psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PD;
+	#if defined(SGX_FEATURE_SYSTEM_CACHE)
+	MMU_InvalidateSystemLevelCache(psDevInfo);
+	#endif
+}
+
+
+IMG_VOID MMU_InvalidatePageTableCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+	psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PT;
+	#if defined(SGX_FEATURE_SYSTEM_CACHE)
+	MMU_InvalidateSystemLevelCache(psDevInfo);
+	#endif
+}
+
+
+static IMG_BOOL
+_AllocPageTableMemory (MMU_HEAP *pMMUHeap,
+						MMU_PT_INFO *psPTInfoList,
+						IMG_DEV_PHYADDR	*psDevPAddr)
+{
+	IMG_DEV_PHYADDR	sDevPAddr;
+	IMG_CPU_PHYADDR sCpuPAddr;
+
+
+
+
+	if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL)
+	{
+
+		if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+						   pMMUHeap->ui32PTSize,
+						   SGX_MMU_PAGE_SIZE,
+						   (IMG_VOID **)&psPTInfoList->PTPageCpuVAddr,
+						   &psPTInfoList->hPTPageOSMemHandle) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR call to OSAllocPages failed"));
+			return IMG_FALSE;
+		}
+
+
+		if(psPTInfoList->PTPageCpuVAddr)
+		{
+			sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->PTPageCpuVAddr);
+		}
+		else
+		{
+
+			sCpuPAddr = OSMemHandleToCpuPAddr(psPTInfoList->hPTPageOSMemHandle, 0);
+		}
+
+		sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+	}
+	else
+	{
+		IMG_SYS_PHYADDR sSysPAddr;
+
+
+
+
+
+		if(RA_Alloc(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena,
+					SGX_MMU_PAGE_SIZE,
+					IMG_NULL,
+					IMG_NULL,
+					0,
+					SGX_MMU_PAGE_SIZE,
+					0,
+					&(sSysPAddr.uiAddr))!= IMG_TRUE)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR call to RA_Alloc failed"));
+			return IMG_FALSE;
+		}
+
+
+		sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+
+		psPTInfoList->PTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+													SGX_MMU_PAGE_SIZE,
+													PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+													&psPTInfoList->hPTPageOSMemHandle);
+		if(!psPTInfoList->PTPageCpuVAddr)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR failed to map page tables"));
+			return IMG_FALSE;
+		}
+
+
+		sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+		#if PAGE_TEST
+		PageTest(psPTInfoList->PTPageCpuVAddr, sDevPAddr);
+		#endif
+	}
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+	{
+		IMG_UINT32 *pui32Tmp;
+		IMG_UINT32 i;
+
+		pui32Tmp = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr;
+
+		for(i=0; i<pMMUHeap->ui32PTECount; i++)
+		{
+			pui32Tmp[i] = (pMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+						| SGX_MMU_PTE_VALID;
+		}
+	}
+#else
+
+	OSMemSet(psPTInfoList->PTPageCpuVAddr, 0, pMMUHeap->ui32PTSize);
+#endif
+
+
+	PDUMPMALLOCPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, PDUMP_PT_UNIQUETAG);
+
+	PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+
+	*psDevPAddr = sDevPAddr;
+
+	return IMG_TRUE;
+}
+
+
+static IMG_VOID
+_FreePageTableMemory (MMU_HEAP *pMMUHeap, MMU_PT_INFO *psPTInfoList)
+{
+
+
+
+
+	if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL)
+	{
+
+		OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+					  pMMUHeap->ui32PTSize,
+					  psPTInfoList->PTPageCpuVAddr,
+					  psPTInfoList->hPTPageOSMemHandle);
+	}
+	else
+	{
+		IMG_SYS_PHYADDR sSysPAddr;
+		IMG_CPU_PHYADDR sCpuPAddr;
+
+
+		sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->PTPageCpuVAddr);
+		sSysPAddr = SysCpuPAddrToSysPAddr (sCpuPAddr);
+
+
+
+		OSUnMapPhysToLin(psPTInfoList->PTPageCpuVAddr,
+                         SGX_MMU_PAGE_SIZE,
+                         PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+                         psPTInfoList->hPTPageOSMemHandle);
+
+
+
+
+		RA_Free (pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+	}
+}
+
+
+
+static IMG_VOID
+_DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOSFreePT)
+{
+	IMG_UINT32 *pui32PDEntry;
+	IMG_UINT32 i;
+	IMG_UINT32 ui32PDIndex;
+	SYS_DATA *psSysData;
+	MMU_PT_INFO **ppsPTInfoList;
+
+	SysAcquireData(&psSysData);
+
+
+	ui32PDIndex = pMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+	ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+	{
+#if PT_DEBUG
+		if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount > 0)
+		{
+			DumpPT(ppsPTInfoList[ui32PTIndex]);
+
+		}
+#endif
+
+
+		PVR_ASSERT(ppsPTInfoList[ui32PTIndex] == IMG_NULL || ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount == 0);
+	}
+
+
+	PDUMPCOMMENT("Free page table (page count == %08X)", pMMUHeap->ui32PageTableCount);
+	if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr)
+	{
+		PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr, pMMUHeap->ui32PTSize, PDUMP_PT_UNIQUETAG);
+	}
+
+	switch(pMMUHeap->psDevArena->DevMemHeapType)
+	{
+		case DEVICE_MEMORY_HEAP_SHARED :
+		case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
+		{
+
+			MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+
+			while(psMMUContext)
+			{
+
+				pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr;
+				pui32PDEntry += ui32PDIndex;
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+				pui32PDEntry[ui32PTIndex] = (psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr
+											>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+											| SGX_MMU_PDE_PAGE_SIZE_4K
+											| SGX_MMU_PDE_VALID;
+#else
+
+				if(bOSFreePT)
+				{
+					pui32PDEntry[ui32PTIndex] = 0;
+				}
+#endif
+
+
+				PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+
+				psMMUContext = psMMUContext->psNext;
+			}
+			break;
+		}
+		case DEVICE_MEMORY_HEAP_PERCONTEXT :
+		case DEVICE_MEMORY_HEAP_KERNEL :
+		{
+
+			pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr;
+			pui32PDEntry += ui32PDIndex;
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+			pui32PDEntry[ui32PTIndex] = (pMMUHeap->psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr
+										>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+										| SGX_MMU_PDE_PAGE_SIZE_4K
+										| SGX_MMU_PDE_VALID;
+#else
+
+			if(bOSFreePT)
+			{
+				pui32PDEntry[ui32PTIndex] = 0;
+			}
+#endif
+
+
+			PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+			break;
+		}
+		default:
+		{
+			PVR_DPF((PVR_DBG_ERROR, "_DeferredFreePagetable: ERROR invalid heap type"));
+			return;
+		}
+	}
+
+
+	if(ppsPTInfoList[ui32PTIndex] != IMG_NULL)
+	{
+		if(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr != IMG_NULL)
+		{
+			IMG_PUINT32 pui32Tmp;
+
+			pui32Tmp = (IMG_UINT32*)ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr;
+
+
+			for(i=0;
+				(i<pMMUHeap->ui32PTETotal) && (i<pMMUHeap->ui32PTECount);
+				 i++)
+			{
+				pui32Tmp[i] = 0;
+			}
+
+
+
+			if(bOSFreePT)
+			{
+				_FreePageTableMemory(pMMUHeap, ppsPTInfoList[ui32PTIndex]);
+			}
+
+
+
+
+			pMMUHeap->ui32PTETotal -= i;
+		}
+		else
+		{
+
+			pMMUHeap->ui32PTETotal -= pMMUHeap->ui32PTECount;
+		}
+
+		if(bOSFreePT)
+		{
+
+			OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof(MMU_PT_INFO),
+						ppsPTInfoList[ui32PTIndex],
+						IMG_NULL);
+			ppsPTInfoList[ui32PTIndex] = IMG_NULL;
+		}
+	}
+	else
+	{
+
+		pMMUHeap->ui32PTETotal -= pMMUHeap->ui32PTECount;
+	}
+
+	PDUMPCOMMENT("Finished free page table (page count == %08X)", pMMUHeap->ui32PageTableCount);
+}
+
+static IMG_VOID
+_DeferredFreePageTables (MMU_HEAP *pMMUHeap)
+{
+	IMG_UINT32 i;
+
+	for(i=0; i<pMMUHeap->ui32PageTableCount; i++)
+	{
+		_DeferredFreePageTable(pMMUHeap, i, IMG_TRUE);
+	}
+	MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
+}
+
+
+static IMG_BOOL
+_DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
+{
+	IMG_UINT32 ui32PageTableCount;
+	IMG_UINT32 ui32PDIndex;
+	IMG_UINT32 i;
+	IMG_UINT32 *pui32PDEntry;
+	MMU_PT_INFO **ppsPTInfoList;
+	SYS_DATA *psSysData;
+	IMG_DEV_VIRTADDR sHighDevVAddr;
+
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE < 32
+	PVR_ASSERT(DevVAddr.uiAddr < (1<<SGX_FEATURE_ADDRESS_SPACE_SIZE));
+#endif
+
+
+	SysAcquireData(&psSysData);
+
+
+	ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+
+	if((UINT32_MAX_VALUE - DevVAddr.uiAddr)
+		< (ui32Size + pMMUHeap->ui32DataPageMask + pMMUHeap->ui32PTMask))
+	{
+
+		sHighDevVAddr.uiAddr = UINT32_MAX_VALUE;
+	}
+	else
+	{
+		sHighDevVAddr.uiAddr = DevVAddr.uiAddr
+								+ ui32Size
+								+ pMMUHeap->ui32DataPageMask
+								+ pMMUHeap->ui32PTMask;
+	}
+
+	ui32PageTableCount = sHighDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+	ui32PageTableCount -= ui32PDIndex;
+
+
+	pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr;
+	pui32PDEntry += ui32PDIndex;
+
+
+	ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+	PDUMPCOMMENT("Alloc page table (page count == %08X)", ui32PageTableCount);
+	PDUMPCOMMENT("Page directory mods (page count == %08X)", ui32PageTableCount);
+
+
+	for(i=0; i<ui32PageTableCount; i++)
+	{
+		if(ppsPTInfoList[i] == IMG_NULL)
+		{
+			OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						 sizeof (MMU_PT_INFO),
+						 (IMG_VOID **)&ppsPTInfoList[i], IMG_NULL,
+						 "MMU Page Table Info");
+			if (ppsPTInfoList[i] == IMG_NULL)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR call to OSAllocMem failed"));
+				return IMG_FALSE;
+			}
+			OSMemSet (ppsPTInfoList[i], 0, sizeof(MMU_PT_INFO));
+		}
+
+		if(ppsPTInfoList[i]->hPTPageOSMemHandle == IMG_NULL
+		&& ppsPTInfoList[i]->PTPageCpuVAddr == IMG_NULL)
+		{
+			IMG_DEV_PHYADDR	sDevPAddr;
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+			IMG_UINT32 *pui32Tmp;
+			IMG_UINT32 j;
+#else
+
+			PVR_ASSERT(pui32PDEntry[i] == 0);
+#endif
+
+			if(_AllocPageTableMemory (pMMUHeap, ppsPTInfoList[i], &sDevPAddr) != IMG_TRUE)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR call to _AllocPageTableMemory failed"));
+				return IMG_FALSE;
+			}
+
+			switch(pMMUHeap->psDevArena->DevMemHeapType)
+			{
+				case DEVICE_MEMORY_HEAP_SHARED :
+				case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
+				{
+
+					MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+
+					while(psMMUContext)
+					{
+
+						pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr;
+						pui32PDEntry += ui32PDIndex;
+
+
+						pui32PDEntry[i] = (sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+										| pMMUHeap->ui32PDEPageSizeCtrl
+										| SGX_MMU_PDE_VALID;
+
+
+						PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+
+						psMMUContext = psMMUContext->psNext;
+					}
+					break;
+				}
+				case DEVICE_MEMORY_HEAP_PERCONTEXT :
+				case DEVICE_MEMORY_HEAP_KERNEL :
+				{
+
+					pui32PDEntry[i] = (sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+									| pMMUHeap->ui32PDEPageSizeCtrl
+									| SGX_MMU_PDE_VALID;
+
+
+					PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+					break;
+				}
+				default:
+				{
+					PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR invalid heap type"));
+					return IMG_FALSE;
+				}
+			}
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+
+
+
+
+			MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
+#endif
+		}
+		else
+		{
+
+			PVR_ASSERT(pui32PDEntry[i] != 0);
+		}
+	}
+
+	#if defined(SGX_FEATURE_SYSTEM_CACHE)
+	MMU_InvalidateSystemLevelCache(pMMUHeap->psMMUContext->psDevInfo);
+	#endif
+
+	return IMG_TRUE;
+}
+
+
+PVRSRV_ERROR
+MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr)
+{
+	IMG_UINT32 *pui32Tmp;
+	IMG_UINT32 i;
+	IMG_CPU_VIRTADDR pvPDCpuVAddr;
+	IMG_DEV_PHYADDR sPDDevPAddr;
+	IMG_CPU_PHYADDR sCpuPAddr;
+	MMU_CONTEXT *psMMUContext;
+	IMG_HANDLE hPDOSMemHandle;
+	SYS_DATA *psSysData;
+	PVRSRV_SGXDEV_INFO *psDevInfo;
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Initialise"));
+
+	SysAcquireData(&psSysData);
+
+	OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				 sizeof (MMU_CONTEXT),
+				 (IMG_VOID **)&psMMUContext, IMG_NULL,
+				 "MMU Context");
+	if (psMMUContext == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocMem failed"));
+		return PVRSRV_ERROR_GENERIC;
+	}
+	OSMemSet (psMMUContext, 0, sizeof(MMU_CONTEXT));
+
+
+	psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+	psMMUContext->psDevInfo = psDevInfo;
+
+
+	psMMUContext->psDeviceNode = psDeviceNode;
+
+
+	if(psDeviceNode->psLocalDevMemArena == IMG_NULL)
+	{
+		if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+							SGX_MMU_PAGE_SIZE,
+							SGX_MMU_PAGE_SIZE,
+							&pvPDCpuVAddr,
+							&hPDOSMemHandle) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+			return PVRSRV_ERROR_GENERIC;
+		}
+
+		if(pvPDCpuVAddr)
+		{
+			sCpuPAddr = OSMapLinToCPUPhys(pvPDCpuVAddr);
+		}
+		else
+		{
+
+			sCpuPAddr = OSMemHandleToCpuPAddr(hPDOSMemHandle, 0);
+		}
+		sPDDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+		#if PAGE_TEST
+		PageTest(pvPDCpuVAddr, sPDDevPAddr);
+		#endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+		if(!psDevInfo->pvMMUContextList)
+		{
+
+			if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+								SGX_MMU_PAGE_SIZE,
+								SGX_MMU_PAGE_SIZE,
+								&psDevInfo->pvDummyPTPageCpuVAddr,
+								&psDevInfo->hDummyPTPageOSMemHandle) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+				return PVRSRV_ERROR_GENERIC;
+			}
+
+			if(psDevInfo->pvDummyPTPageCpuVAddr)
+			{
+				sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->pvDummyPTPageCpuVAddr);
+			}
+			else
+			{
+
+				sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hDummyPTPageOSMemHandle, 0);
+			}
+			psDevInfo->sDummyPTDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+
+			if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+								SGX_MMU_PAGE_SIZE,
+								SGX_MMU_PAGE_SIZE,
+								&psDevInfo->pvDummyDataPageCpuVAddr,
+								&psDevInfo->hDummyDataPageOSMemHandle) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+				return PVRSRV_ERROR_GENERIC;
+			}
+
+			if(psDevInfo->pvDummyDataPageCpuVAddr)
+			{
+				sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->pvDummyDataPageCpuVAddr);
+			}
+			else
+			{
+				sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hDummyDataPageOSMemHandle, 0);
+			}
+			psDevInfo->sDummyDataDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+		}
+#endif
+	}
+	else
+	{
+		IMG_SYS_PHYADDR sSysPAddr;
+
+
+		if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+					SGX_MMU_PAGE_SIZE,
+					IMG_NULL,
+					IMG_NULL,
+					0,
+					SGX_MMU_PAGE_SIZE,
+					0,
+					&(sSysPAddr.uiAddr))!= IMG_TRUE)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+			return PVRSRV_ERROR_GENERIC;
+		}
+
+
+		sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+		sPDDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+		pvPDCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+										SGX_MMU_PAGE_SIZE,
+										PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+										&hPDOSMemHandle);
+		if(!pvPDCpuVAddr)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+			return PVRSRV_ERROR_GENERIC;
+		}
+
+		#if PAGE_TEST
+		PageTest(pvPDCpuVAddr, sPDDevPAddr);
+		#endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+		if(!psDevInfo->pvMMUContextList)
+		{
+
+			if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+						SGX_MMU_PAGE_SIZE,
+						IMG_NULL,
+						IMG_NULL,
+						0,
+						SGX_MMU_PAGE_SIZE,
+						0,
+						&(sSysPAddr.uiAddr))!= IMG_TRUE)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+				return PVRSRV_ERROR_GENERIC;
+			}
+
+
+			sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+			psDevInfo->sDummyPTDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+			psDevInfo->pvDummyPTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+																SGX_MMU_PAGE_SIZE,
+																PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+																&psDevInfo->hDummyPTPageOSMemHandle);
+			if(!psDevInfo->pvDummyPTPageCpuVAddr)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+				return PVRSRV_ERROR_GENERIC;
+			}
+
+
+			if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+						SGX_MMU_PAGE_SIZE,
+						IMG_NULL,
+						IMG_NULL,
+						0,
+						SGX_MMU_PAGE_SIZE,
+						0,
+						&(sSysPAddr.uiAddr))!= IMG_TRUE)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+				return PVRSRV_ERROR_GENERIC;
+			}
+
+
+			sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+			psDevInfo->sDummyDataDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+			psDevInfo->pvDummyDataPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+																SGX_MMU_PAGE_SIZE,
+																PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+																&psDevInfo->hDummyDataPageOSMemHandle);
+			if(!psDevInfo->pvDummyDataPageCpuVAddr)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+				return PVRSRV_ERROR_GENERIC;
+			}
+		}
+#endif
+	}
+
+
+	PDUMPCOMMENT("Alloc page directory");
+#ifdef SUPPORT_SGX_MMU_BYPASS
+	EnableHostAccess(psMMUContext);
+#endif
+
+	PDUMPMALLOCPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, PDUMP_PD_UNIQUETAG);
+
+	if (pvPDCpuVAddr)
+	{
+		pui32Tmp = (IMG_UINT32 *)pvPDCpuVAddr;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: pvPDCpuVAddr invalid"));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+	for(i=0; i<SGX_MMU_PD_SIZE; i++)
+	{
+		pui32Tmp[i] = (psDevInfo->sDummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+					| SGX_MMU_PDE_PAGE_SIZE_4K
+					| SGX_MMU_PDE_VALID;
+	}
+
+	if(!psDevInfo->pvMMUContextList)
+	{
+
+
+
+		pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyPTPageCpuVAddr;
+		for(i=0; i<SGX_MMU_PT_SIZE; i++)
+		{
+			pui32Tmp[i] = (psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+						| SGX_MMU_PTE_VALID;
+		}
+
+		PDUMPCOMMENT("Dummy Page table contents");
+		PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+
+
+		pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyDataPageCpuVAddr;
+		for(i=0; i<(SGX_MMU_PAGE_SIZE/4); i++)
+		{
+			pui32Tmp[i] = DUMMY_DATA_PAGE_SIGNATURE;
+		}
+
+		PDUMPCOMMENT("Dummy Data Page contents");
+		PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->pvDummyDataPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+	}
+#else
+
+	for(i=0; i<SGX_MMU_PD_SIZE; i++)
+	{
+
+		pui32Tmp[i] = 0;
+	}
+#endif
+
+
+	PDUMPCOMMENT("Page directory contents");
+	PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+
+#if defined(PDUMP)
+	if(PDumpSetMMUContext(PVRSRV_DEVICE_TYPE_SGX,
+							"SGXMEM",
+							&psMMUContext->ui32PDumpMMUContextID,
+							2,
+							PDUMP_PT_UNIQUETAG,
+							pvPDCpuVAddr) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to PDumpSetMMUContext failed"));
+		return PVRSRV_ERROR_GENERIC;
+	}
+#endif
+
+
+	psMMUContext->pvPDCpuVAddr = pvPDCpuVAddr;
+	psMMUContext->sPDDevPAddr = sPDDevPAddr;
+	psMMUContext->hPDOSMemHandle = hPDOSMemHandle;
+
+
+	*ppsMMUContext = psMMUContext;
+
+
+	*psPDDevPAddr = sPDDevPAddr;
+
+
+	psMMUContext->psNext = (MMU_CONTEXT*)psDevInfo->pvMMUContextList;
+	psDevInfo->pvMMUContextList = (IMG_VOID*)psMMUContext;
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+	DisableHostAccess(psMMUContext);
+#endif
+
+	return PVRSRV_OK;
+}
+
+IMG_VOID
+MMU_Finalise (MMU_CONTEXT *psMMUContext)
+{
+	IMG_UINT32 *pui32Tmp, i;
+	SYS_DATA *psSysData;
+	MMU_CONTEXT **ppsMMUContext;
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+	PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psMMUContext->psDevInfo;
+	MMU_CONTEXT *psMMUContextList = (MMU_CONTEXT*)psDevInfo->pvMMUContextList;
+#endif
+
+	SysAcquireData(&psSysData);
+
+
+	PDUMPCLEARMMUCONTEXT(PVRSRV_DEVICE_TYPE_SGX, "SGXMEM", psMMUContext->ui32PDumpMMUContextID, 2);
+
+
+	PDUMPCOMMENT("Free page directory");
+	PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, psMMUContext->pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+	PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+	PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->pvDummyDataPageCpuVAddr, SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+#endif
+
+	pui32Tmp = (IMG_UINT32 *)psMMUContext->pvPDCpuVAddr;
+
+
+	for(i=0; i<SGX_MMU_PD_SIZE; i++)
+	{
+
+		pui32Tmp[i] = 0;
+	}
+
+
+
+
+
+	if(psMMUContext->psDeviceNode->psLocalDevMemArena == IMG_NULL)
+	{
+		OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+						SGX_MMU_PAGE_SIZE,
+						psMMUContext->pvPDCpuVAddr,
+						psMMUContext->hPDOSMemHandle);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+		if(!psMMUContextList->psNext)
+		{
+			OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+							SGX_MMU_PAGE_SIZE,
+							psDevInfo->pvDummyPTPageCpuVAddr,
+							psDevInfo->hDummyPTPageOSMemHandle);
+			OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+							SGX_MMU_PAGE_SIZE,
+							psDevInfo->pvDummyDataPageCpuVAddr,
+							psDevInfo->hDummyDataPageOSMemHandle);
+		}
+#endif
+	}
+	else
+	{
+		IMG_SYS_PHYADDR sSysPAddr;
+		IMG_CPU_PHYADDR sCpuPAddr;
+
+
+		sCpuPAddr = OSMapLinToCPUPhys(psMMUContext->pvPDCpuVAddr);
+		sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+
+		OSUnMapPhysToLin(psMMUContext->pvPDCpuVAddr,
+							SGX_MMU_PAGE_SIZE,
+                            PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+							psMMUContext->hPDOSMemHandle);
+
+		RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+		if(!psMMUContextList->psNext)
+		{
+
+			sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->pvDummyPTPageCpuVAddr);
+			sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+
+			OSUnMapPhysToLin(psDevInfo->pvDummyPTPageCpuVAddr,
+								SGX_MMU_PAGE_SIZE,
+                                PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+								psDevInfo->hDummyPTPageOSMemHandle);
+
+			RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+
+
+			sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->pvDummyDataPageCpuVAddr);
+			sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+
+			OSUnMapPhysToLin(psDevInfo->pvDummyDataPageCpuVAddr,
+								SGX_MMU_PAGE_SIZE,
+                                PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+								psDevInfo->hDummyDataPageOSMemHandle);
+
+			RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+		}
+#endif
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Finalise"));
+
+
+	ppsMMUContext = (MMU_CONTEXT**)&psMMUContext->psDevInfo->pvMMUContextList;
+	while(*ppsMMUContext)
+	{
+		if(*ppsMMUContext == psMMUContext)
+		{
+
+			*ppsMMUContext = psMMUContext->psNext;
+			break;
+		}
+
+
+		ppsMMUContext = &((*ppsMMUContext)->psNext);
+	}
+
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_CONTEXT), psMMUContext, IMG_NULL);
+
+}
+
+
+IMG_VOID
+MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap)
+{
+	IMG_UINT32 *pui32PDCpuVAddr = (IMG_UINT32 *) psMMUContext->pvPDCpuVAddr;
+	IMG_UINT32 *pui32KernelPDCpuVAddr = (IMG_UINT32 *) psMMUHeap->psMMUContext->pvPDCpuVAddr;
+	IMG_UINT32 ui32PDEntry;
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+	IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE;
+#endif
+
+
+	pui32PDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+	pui32KernelPDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+
+
+
+	PDUMPCOMMENT("Page directory shared heap range copy");
+#ifdef SUPPORT_SGX_MMU_BYPASS
+	EnableHostAccess(psMMUContext);
+#endif
+
+	for (ui32PDEntry = 0; ui32PDEntry < psMMUHeap->ui32PageTableCount; ui32PDEntry++)
+	{
+#if !defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+		PVR_ASSERT(pui32PDCpuVAddr[ui32PDEntry] == 0);
+#endif
+
+
+		pui32PDCpuVAddr[ui32PDEntry] = pui32KernelPDCpuVAddr[ui32PDEntry];
+		if (pui32PDCpuVAddr[ui32PDEntry])
+		{
+			PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, (IMG_VOID *) &pui32PDCpuVAddr[ui32PDEntry], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+			bInvalidateDirectoryCache = IMG_TRUE;
+#endif
+		}
+	}
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+	DisableHostAccess(psMMUContext);
+#endif
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+	if (bInvalidateDirectoryCache)
+	{
+
+
+
+
+		MMU_InvalidateDirectoryCache(psMMUContext->psDevInfo);
+	}
+#endif
+}
+
+
+static IMG_VOID
+MMU_UnmapPagesAndFreePTs (MMU_HEAP *psMMUHeap,
+						  IMG_DEV_VIRTADDR sDevVAddr,
+						  IMG_UINT32 ui32PageCount,
+						  IMG_HANDLE hUniqueTag)
+{
+	IMG_DEV_VIRTADDR	sTmpDevVAddr;
+	IMG_UINT32			i;
+	IMG_UINT32			ui32PDIndex;
+	IMG_UINT32			ui32PTIndex;
+	IMG_UINT32			*pui32Tmp;
+	IMG_BOOL			bInvalidateDirectoryCache = IMG_FALSE;
+
+#if !defined (PDUMP)
+	PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+	sTmpDevVAddr = sDevVAddr;
+
+	for(i=0; i<ui32PageCount; i++)
+	{
+		MMU_PT_INFO **ppsPTInfoList;
+
+
+		ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+
+		ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+		{
+
+			ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift;
+
+
+			if (!ppsPTInfoList[0])
+			{
+				PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Invalid PT for alloc at VAddr:0x%08lX (VaddrIni:0x%08lX AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+
+
+				sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize;
+
+
+				continue;
+			}
+
+
+			pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+
+			if (!pui32Tmp)
+			{
+				continue;
+			}
+
+			CheckPT(ppsPTInfoList[0]);
+
+
+			if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
+			{
+				ppsPTInfoList[0]->ui32ValidPTECount--;
+			}
+			else
+			{
+				PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Page is already invalid for alloc at VAddr:0x%08lX (VAddrIni:0x%08lX AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+			}
+
+
+			PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+			pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+									| SGX_MMU_PTE_VALID;
+#else
+
+			pui32Tmp[ui32PTIndex] = 0;
+#endif
+
+			CheckPT(ppsPTInfoList[0]);
+		}
+
+
+
+		if (ppsPTInfoList[0] && ppsPTInfoList[0]->ui32ValidPTECount == 0)
+		{
+			_DeferredFreePageTable(psMMUHeap, ui32PDIndex - psMMUHeap->ui32PDBaseIndex, IMG_TRUE);
+			bInvalidateDirectoryCache = IMG_TRUE;
+		}
+
+
+		sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize;
+	}
+
+	if(bInvalidateDirectoryCache)
+	{
+		MMU_InvalidateDirectoryCache(psMMUHeap->psMMUContext->psDevInfo);
+	}
+	else
+	{
+		MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->psDevInfo);
+	}
+
+#if defined(PDUMP)
+	MMU_PDumpPageTables(psMMUHeap,
+						sDevVAddr,
+						psMMUHeap->ui32DataPageSize * ui32PageCount,
+						IMG_TRUE,
+						hUniqueTag);
+#endif
+}
+
+
+IMG_VOID MMU_FreePageTables(IMG_PVOID pvMMUHeap,
+                            IMG_SIZE_T ui32Start,
+                            IMG_SIZE_T ui32End,
+                            IMG_HANDLE hUniqueTag)
+{
+	MMU_HEAP *pMMUHeap = (MMU_HEAP*)pvMMUHeap;
+	IMG_DEV_VIRTADDR Start;
+
+	Start.uiAddr = ui32Start;
+
+	MMU_UnmapPagesAndFreePTs(pMMUHeap, Start, (ui32End - ui32Start) >> pMMUHeap->ui32PTShift, hUniqueTag);
+}
+
+MMU_HEAP *
+MMU_Create (MMU_CONTEXT *psMMUContext,
+			DEV_ARENA_DESCRIPTOR *psDevArena,
+			RA_ARENA **ppsVMArena)
+{
+	MMU_HEAP *pMMUHeap;
+	IMG_UINT32 ui32ScaleSize;
+
+	PVR_ASSERT (psDevArena != IMG_NULL);
+
+	if (psDevArena == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "MMU_Create: invalid parameter"));
+		return IMG_NULL;
+	}
+
+	OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				 sizeof (MMU_HEAP),
+				 (IMG_VOID **)&pMMUHeap, IMG_NULL,
+				 "MMU Heap");
+	if (pMMUHeap == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to OSAllocMem failed"));
+		return IMG_NULL;
+	}
+
+	pMMUHeap->psMMUContext = psMMUContext;
+	pMMUHeap->psDevArena = psDevArena;
+
+
+
+
+	switch(pMMUHeap->psDevArena->ui32DataPageSize)
+	{
+		case 0x1000:
+			ui32ScaleSize = 0;
+			pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_4K;
+			break;
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+		case 0x4000:
+			ui32ScaleSize = 2;
+			pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_16K;
+			break;
+		case 0x10000:
+			ui32ScaleSize = 4;
+			pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_64K;
+			break;
+		case 0x40000:
+			ui32ScaleSize = 6;
+			pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_256K;
+			break;
+		case 0x100000:
+			ui32ScaleSize = 8;
+			pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_1M;
+			break;
+		case 0x400000:
+			ui32ScaleSize = 10;
+			pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_4M;
+			break;
+#endif
+		default:
+			PVR_DPF((PVR_DBG_ERROR, "MMU_Create: invalid data page size"));
+			goto ErrorFreeHeap;
+	}
+
+
+	pMMUHeap->ui32DataPageSize = psDevArena->ui32DataPageSize;
+	pMMUHeap->ui32DataPageBitWidth = SGX_MMU_PAGE_SHIFT + ui32ScaleSize;
+	pMMUHeap->ui32DataPageMask = pMMUHeap->ui32DataPageSize - 1;
+
+	pMMUHeap->ui32PTShift = pMMUHeap->ui32DataPageBitWidth;
+	pMMUHeap->ui32PTBitWidth = SGX_MMU_PT_SHIFT - ui32ScaleSize;
+	pMMUHeap->ui32PTMask = SGX_MMU_PT_MASK & (SGX_MMU_PT_MASK<<ui32ScaleSize);
+	pMMUHeap->ui32PTSize = (1UL<<pMMUHeap->ui32PTBitWidth) * sizeof(IMG_UINT32);
+
+	if(pMMUHeap->ui32PTSize < 4 * sizeof(IMG_UINT32))
+	{
+		pMMUHeap->ui32PTSize = 4 * sizeof(IMG_UINT32);
+	}
+	pMMUHeap->ui32PTECount = pMMUHeap->ui32PTSize >> 2;
+
+
+	pMMUHeap->ui32PDShift = pMMUHeap->ui32PTBitWidth + pMMUHeap->ui32PTShift;
+	pMMUHeap->ui32PDBitWidth = SGX_FEATURE_ADDRESS_SPACE_SIZE - pMMUHeap->ui32PTBitWidth - pMMUHeap->ui32DataPageBitWidth;
+	pMMUHeap->ui32PDMask = SGX_MMU_PD_MASK & (SGX_MMU_PD_MASK>>(32-SGX_FEATURE_ADDRESS_SPACE_SIZE));
+
+
+
+
+
+	if(psDevArena->BaseDevVAddr.uiAddr > (pMMUHeap->ui32DataPageMask | pMMUHeap->ui32PTMask))
+	{
+
+
+
+		PVR_ASSERT ((psDevArena->BaseDevVAddr.uiAddr
+						& (pMMUHeap->ui32DataPageMask
+							| pMMUHeap->ui32PTMask)) == 0);
+	}
+
+
+	pMMUHeap->ui32PTETotal = pMMUHeap->psDevArena->ui32Size >> pMMUHeap->ui32PTShift;
+
+
+	pMMUHeap->ui32PDBaseIndex = (pMMUHeap->psDevArena->BaseDevVAddr.uiAddr & pMMUHeap->ui32PDMask) >> pMMUHeap->ui32PDShift;
+
+
+
+
+	pMMUHeap->ui32PageTableCount = (pMMUHeap->ui32PTETotal + pMMUHeap->ui32PTECount - 1)
+										>> pMMUHeap->ui32PTBitWidth;
+
+
+	pMMUHeap->psVMArena = RA_Create(psDevArena->pszName,
+									psDevArena->BaseDevVAddr.uiAddr,
+									psDevArena->ui32Size,
+									IMG_NULL,
+									pMMUHeap->ui32DataPageSize,
+									IMG_NULL,
+									IMG_NULL,
+									MMU_FreePageTables,
+									pMMUHeap);
+
+	if (pMMUHeap->psVMArena == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to RA_Create failed"));
+		goto ErrorFreePagetables;
+	}
+
+#if 0
+
+	if(psDevArena->ui32HeapID == SGX_TILED_HEAP_ID)
+	{
+		IMG_UINT32 ui32RegVal;
+		IMG_UINT32 ui32XTileStride;
+
+
+
+
+
+
+		ui32XTileStride	= 2;
+
+		ui32RegVal = (EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK
+						& ((psDevArena->BaseDevVAddr.uiAddr>>20)
+						<< EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT))
+					|(EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK
+						& (((psDevArena->BaseDevVAddr.uiAddr+psDevArena->ui32Size)>>20)
+						<< EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT))
+					|(EUR_CR_BIF_TILE0_CFG_MASK
+						& (((ui32XTileStride<<1)|8) << EUR_CR_BIF_TILE0_CFG_SHIFT));
+		PDUMPREG(EUR_CR_BIF_TILE0, ui32RegVal);
+	}
+#endif
+
+
+
+	*ppsVMArena = pMMUHeap->psVMArena;
+
+	return pMMUHeap;
+
+
+ErrorFreePagetables:
+	_DeferredFreePageTables (pMMUHeap);
+
+ErrorFreeHeap:
+	OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL);
+
+
+	return IMG_NULL;
+}
+
+IMG_VOID
+MMU_Delete (MMU_HEAP *pMMUHeap)
+{
+	if (pMMUHeap != IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Delete"));
+
+		if(pMMUHeap->psVMArena)
+		{
+			RA_Delete (pMMUHeap->psVMArena);
+		}
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+		EnableHostAccess(pMMUHeap->psMMUContext);
+#endif
+		_DeferredFreePageTables (pMMUHeap);
+#ifdef SUPPORT_SGX_MMU_BYPASS
+		DisableHostAccess(pMMUHeap->psMMUContext);
+#endif
+
+		OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL);
+
+	}
+}
+
+IMG_BOOL
+MMU_Alloc (MMU_HEAP *pMMUHeap,
+		   IMG_SIZE_T uSize,
+		   IMG_SIZE_T *pActualSize,
+		   IMG_UINT32 uFlags,
+		   IMG_UINT32 uDevVAddrAlignment,
+		   IMG_DEV_VIRTADDR *psDevVAddr)
+{
+	IMG_BOOL bStatus;
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+		"MMU_Alloc: uSize=0x%x, flags=0x%x, align=0x%x",
+		uSize, uFlags, uDevVAddrAlignment));
+
+
+
+	if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
+	{
+		IMG_UINTPTR_T uiAddr;
+
+		bStatus = RA_Alloc (pMMUHeap->psVMArena,
+							uSize,
+							pActualSize,
+							IMG_NULL,
+							0,
+							uDevVAddrAlignment,
+							0,
+							&uiAddr);
+		if(!bStatus)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: RA_Alloc of VMArena failed"));
+			return bStatus;
+		}
+
+		psDevVAddr->uiAddr = IMG_CAST_TO_DEVVADDR_UINT(uiAddr);
+	}
+
+	#ifdef SUPPORT_SGX_MMU_BYPASS
+	EnableHostAccess(pMMUHeap->psMMUContext);
+	#endif
+
+
+	bStatus = _DeferredAllocPagetables(pMMUHeap, *psDevVAddr, uSize);
+
+	#ifdef SUPPORT_SGX_MMU_BYPASS
+	DisableHostAccess(pMMUHeap->psMMUContext);
+	#endif
+
+	if (!bStatus)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: _DeferredAllocPagetables failed"));
+		if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
+		{
+
+			RA_Free (pMMUHeap->psVMArena, psDevVAddr->uiAddr, IMG_FALSE);
+		}
+	}
+
+	return bStatus;
+}
+
+IMG_VOID
+MMU_Free (MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
+{
+	PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+	if (pMMUHeap == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "MMU_Free: invalid parameter"));
+		return;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+		"MMU_Free: mmu=%08X, dev_vaddr=%08X", pMMUHeap, DevVAddr.uiAddr));
+
+	if((DevVAddr.uiAddr >= pMMUHeap->psDevArena->BaseDevVAddr.uiAddr) &&
+		(DevVAddr.uiAddr + ui32Size <= pMMUHeap->psDevArena->BaseDevVAddr.uiAddr + pMMUHeap->psDevArena->ui32Size))
+	{
+		RA_Free (pMMUHeap->psVMArena, DevVAddr.uiAddr, IMG_TRUE);
+		return;
+	}
+
+	PVR_DPF((PVR_DBG_ERROR,"MMU_Free: Couldn't find DevVAddr %08X in a DevArena",DevVAddr.uiAddr));
+}
+
+IMG_VOID
+MMU_Enable (MMU_HEAP *pMMUHeap)
+{
+	PVR_UNREFERENCED_PARAMETER(pMMUHeap);
+
+}
+
+IMG_VOID
+MMU_Disable (MMU_HEAP *pMMUHeap)
+{
+	PVR_UNREFERENCED_PARAMETER(pMMUHeap);
+
+}
+
+#if defined(PDUMP)
+static IMG_VOID
+MMU_PDumpPageTables	(MMU_HEAP *pMMUHeap,
+					 IMG_DEV_VIRTADDR DevVAddr,
+					 IMG_SIZE_T uSize,
+					 IMG_BOOL bForUnmap,
+					 IMG_HANDLE hUniqueTag)
+{
+	IMG_UINT32	ui32NumPTEntries;
+	IMG_UINT32	ui32PTIndex;
+	IMG_UINT32	*pui32PTEntry;
+
+	MMU_PT_INFO **ppsPTInfoList;
+	IMG_UINT32 ui32PDIndex;
+	IMG_UINT32 ui32PTDumpCount;
+
+
+	ui32NumPTEntries = (uSize + pMMUHeap->ui32DataPageMask) >> pMMUHeap->ui32PTShift;
+
+
+	ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+	ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+
+	ui32PTIndex = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+
+	PDUMPCOMMENT("Page table mods (num entries == %08X) %s", ui32NumPTEntries, bForUnmap ? "(for unmap)" : "");
+
+
+	while(ui32NumPTEntries > 0)
+	{
+		MMU_PT_INFO* psPTInfo = *ppsPTInfoList++;
+
+		if(ui32NumPTEntries <= pMMUHeap->ui32PTECount - ui32PTIndex)
+		{
+			ui32PTDumpCount = ui32NumPTEntries;
+		}
+		else
+		{
+			ui32PTDumpCount = pMMUHeap->ui32PTECount - ui32PTIndex;
+		}
+
+		if (psPTInfo)
+		{
+			pui32PTEntry = (IMG_UINT32*)psPTInfo->PTPageCpuVAddr;
+			PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, (IMG_VOID *) &pui32PTEntry[ui32PTIndex], ui32PTDumpCount * sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, hUniqueTag);
+		}
+
+
+		ui32NumPTEntries -= ui32PTDumpCount;
+
+
+		ui32PTIndex = 0;
+	}
+
+	PDUMPCOMMENT("Finished page table mods %s", bForUnmap ? "(for unmap)" : "");
+}
+#endif
+
+
+static IMG_VOID
+MMU_MapPage (MMU_HEAP *pMMUHeap,
+			 IMG_DEV_VIRTADDR DevVAddr,
+			 IMG_DEV_PHYADDR DevPAddr,
+			 IMG_UINT32 ui32MemFlags)
+{
+	IMG_UINT32 ui32Index;
+	IMG_UINT32 *pui32Tmp;
+	IMG_UINT32 ui32MMUFlags = 0;
+	MMU_PT_INFO **ppsPTInfoList;
+
+
+	PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+
+
+	if(((PVRSRV_MEM_READ|PVRSRV_MEM_WRITE) & ui32MemFlags) == (PVRSRV_MEM_READ|PVRSRV_MEM_WRITE))
+	{
+
+		ui32MMUFlags = 0;
+	}
+	else if(PVRSRV_MEM_READ & ui32MemFlags)
+	{
+
+		ui32MMUFlags |= SGX_MMU_PTE_READONLY;
+	}
+	else if(PVRSRV_MEM_WRITE & ui32MemFlags)
+	{
+
+		ui32MMUFlags |= SGX_MMU_PTE_WRITEONLY;
+	}
+
+
+	if(PVRSRV_MEM_CACHE_CONSISTENT & ui32MemFlags)
+	{
+		ui32MMUFlags |= SGX_MMU_PTE_CACHECONSISTENT;
+	}
+
+#if !defined(FIX_HW_BRN_25503)
+
+	if(PVRSRV_MEM_EDM_PROTECT & ui32MemFlags)
+	{
+		ui32MMUFlags |= SGX_MMU_PTE_EDMPROTECT;
+	}
+#endif
+
+
+
+
+
+	ui32Index = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+	ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
+
+	CheckPT(ppsPTInfoList[0]);
+
+
+	ui32Index = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+
+	pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+#if !defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+	if (pui32Tmp[ui32Index] & SGX_MMU_PTE_VALID)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page is already valid for alloc at VAddr:0x%08lX PDIdx:%u PTIdx:%u",
+								DevVAddr.uiAddr,
+								DevVAddr.uiAddr >> pMMUHeap->ui32PDShift,
+								ui32Index ));
+		PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page table entry value: 0x%08lX", pui32Tmp[ui32Index]));
+		PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Physical page to map: 0x%08lX", DevPAddr.uiAddr));
+	}
+
+	PVR_ASSERT((pui32Tmp[ui32Index] & SGX_MMU_PTE_VALID) == 0);
+#endif
+
+
+	ppsPTInfoList[0]->ui32ValidPTECount++;
+
+
+	pui32Tmp[ui32Index] = ((DevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+						& ((~pMMUHeap->ui32DataPageMask)>>SGX_MMU_PTE_ADDR_ALIGNSHIFT))
+						| SGX_MMU_PTE_VALID
+						| ui32MMUFlags;
+
+	CheckPT(ppsPTInfoList[0]);
+}
+
+
+IMG_VOID
+MMU_MapScatter (MMU_HEAP *pMMUHeap,
+				IMG_DEV_VIRTADDR DevVAddr,
+				IMG_SYS_PHYADDR *psSysAddr,
+				IMG_SIZE_T uSize,
+				IMG_UINT32 ui32MemFlags,
+				IMG_HANDLE hUniqueTag)
+{
+#if defined(PDUMP)
+	IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif
+	IMG_UINT32 uCount, i;
+	IMG_DEV_PHYADDR DevPAddr;
+
+	PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+#if defined(PDUMP)
+	MapBaseDevVAddr = DevVAddr;
+#else
+	PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+	for (i=0, uCount=0; uCount<uSize; i++, uCount+=pMMUHeap->ui32DataPageSize)
+	{
+		IMG_SYS_PHYADDR sSysAddr;
+
+		sSysAddr = psSysAddr[i];
+
+
+
+		PVR_ASSERT((sSysAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+		DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysAddr);
+
+		MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+		DevVAddr.uiAddr += pMMUHeap->ui32DataPageSize;
+
+		PVR_DPF ((PVR_DBG_MESSAGE,
+				 "MMU_MapScatter: devVAddr=%08X, SysAddr=%08X, size=0x%x/0x%x",
+				  DevVAddr.uiAddr, sSysAddr.uiAddr, uCount, uSize));
+	}
+
+#if defined(PDUMP)
+	MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
+#endif
+}
+
+IMG_VOID
+MMU_MapPages (MMU_HEAP *pMMUHeap,
+			  IMG_DEV_VIRTADDR DevVAddr,
+			  IMG_SYS_PHYADDR SysPAddr,
+			  IMG_SIZE_T uSize,
+			  IMG_UINT32 ui32MemFlags,
+			  IMG_HANDLE hUniqueTag)
+{
+	IMG_DEV_PHYADDR DevPAddr;
+#if defined(PDUMP)
+	IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif
+	IMG_UINT32 uCount;
+	IMG_UINT32 ui32VAdvance;
+	IMG_UINT32 ui32PAdvance;
+
+	PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+		  "MMU_MapPages: mmu=%08X, devVAddr=%08X, SysPAddr=%08X, size=0x%x",
+		  pMMUHeap, DevVAddr.uiAddr, SysPAddr.uiAddr, uSize));
+
+
+	ui32VAdvance = pMMUHeap->ui32DataPageSize;
+	ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+#if defined(PDUMP)
+	MapBaseDevVAddr = DevVAddr;
+#else
+	PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+	DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, SysPAddr);
+
+
+	PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+#if defined(FIX_HW_BRN_23281)
+	if(ui32MemFlags & PVRSRV_MEM_INTERLEAVED)
+	{
+		ui32VAdvance *= 2;
+	}
+#endif
+
+
+
+
+	if(ui32MemFlags & PVRSRV_MEM_DUMMY)
+	{
+		ui32PAdvance = 0;
+	}
+
+	for (uCount=0; uCount<uSize; uCount+=ui32VAdvance)
+	{
+		MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+		DevVAddr.uiAddr += ui32VAdvance;
+		DevPAddr.uiAddr += ui32PAdvance;
+	}
+
+#if defined(PDUMP)
+	MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
+#endif
+}
+
+IMG_VOID
+MMU_MapShadow (MMU_HEAP          *pMMUHeap,
+			   IMG_DEV_VIRTADDR   MapBaseDevVAddr,
+			   IMG_SIZE_T         uByteSize,
+			   IMG_CPU_VIRTADDR   CpuVAddr,
+			   IMG_HANDLE         hOSMemHandle,
+			   IMG_DEV_VIRTADDR  *pDevVAddr,
+			   IMG_UINT32         ui32MemFlags,
+			   IMG_HANDLE         hUniqueTag)
+{
+	IMG_UINT32			i;
+	IMG_UINT32			uOffset = 0;
+	IMG_DEV_VIRTADDR	MapDevVAddr;
+	IMG_UINT32			ui32VAdvance;
+	IMG_UINT32			ui32PAdvance;
+
+#if !defined (PDUMP)
+	PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			"MMU_MapShadow: %08X, 0x%x, %08X",
+			MapBaseDevVAddr.uiAddr,
+			uByteSize,
+			CpuVAddr));
+
+
+	ui32VAdvance = pMMUHeap->ui32DataPageSize;
+	ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+
+	PVR_ASSERT(((IMG_UINT32)CpuVAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+	PVR_ASSERT(((IMG_UINT32)uByteSize & pMMUHeap->ui32DataPageMask) == 0);
+	pDevVAddr->uiAddr = MapBaseDevVAddr.uiAddr;
+
+#if defined(FIX_HW_BRN_23281)
+	if(ui32MemFlags & PVRSRV_MEM_INTERLEAVED)
+	{
+		ui32VAdvance *= 2;
+	}
+#endif
+
+
+
+
+	if(ui32MemFlags & PVRSRV_MEM_DUMMY)
+	{
+		ui32PAdvance = 0;
+	}
+
+
+	MapDevVAddr = MapBaseDevVAddr;
+	for (i=0; i<uByteSize; i+=ui32VAdvance)
+	{
+		IMG_CPU_PHYADDR CpuPAddr;
+		IMG_DEV_PHYADDR DevPAddr;
+
+		if(CpuVAddr)
+		{
+			CpuPAddr = OSMapLinToCPUPhys ((IMG_VOID *)((IMG_UINT32)CpuVAddr + uOffset));
+		}
+		else
+		{
+			CpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, uOffset);
+		}
+		DevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, CpuPAddr);
+
+
+		PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+		PVR_DPF ((PVR_DBG_MESSAGE,
+				"0x%x: CpuVAddr=%08X, CpuPAddr=%08X, DevVAddr=%08X, DevPAddr=%08X",
+				uOffset,
+				(IMG_UINTPTR_T)CpuVAddr + uOffset,
+				CpuPAddr.uiAddr,
+				MapDevVAddr.uiAddr,
+				DevPAddr.uiAddr));
+
+		MMU_MapPage (pMMUHeap, MapDevVAddr, DevPAddr, ui32MemFlags);
+
+
+		MapDevVAddr.uiAddr += ui32VAdvance;
+		uOffset += ui32PAdvance;
+	}
+
+#if defined(PDUMP)
+	MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uByteSize, IMG_FALSE, hUniqueTag);
+#endif
+}
+
+
+IMG_VOID
+MMU_UnmapPages (MMU_HEAP *psMMUHeap,
+				IMG_DEV_VIRTADDR sDevVAddr,
+				IMG_UINT32 ui32PageCount,
+				IMG_HANDLE hUniqueTag)
+{
+	IMG_UINT32			uPageSize = psMMUHeap->ui32DataPageSize;
+	IMG_DEV_VIRTADDR	sTmpDevVAddr;
+	IMG_UINT32			i;
+	IMG_UINT32			ui32PDIndex;
+	IMG_UINT32			ui32PTIndex;
+	IMG_UINT32			*pui32Tmp;
+
+#if !defined (PDUMP)
+	PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+
+	sTmpDevVAddr = sDevVAddr;
+
+	for(i=0; i<ui32PageCount; i++)
+	{
+		MMU_PT_INFO **ppsPTInfoList;
+
+
+		ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+
+		ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+
+		ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift;
+
+
+		if (!ppsPTInfoList[0])
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: ERROR Invalid PT for alloc at VAddr:0x%08lX (VaddrIni:0x%08lX AllocPage:%u) PDIdx:%u PTIdx:%u",
+									sTmpDevVAddr.uiAddr,
+									sDevVAddr.uiAddr,
+									i,
+									ui32PDIndex,
+									ui32PTIndex));
+
+
+			sTmpDevVAddr.uiAddr += uPageSize;
+
+
+			continue;
+		}
+
+		CheckPT(ppsPTInfoList[0]);
+
+
+		pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+
+		if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
+		{
+			ppsPTInfoList[0]->ui32ValidPTECount--;
+		}
+		else
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: Page is already invalid for alloc at VAddr:0x%08lX (VAddrIni:0x%08lX AllocPage:%u) PDIdx:%u PTIdx:%u",
+									sTmpDevVAddr.uiAddr,
+									sDevVAddr.uiAddr,
+									i,
+									ui32PDIndex,
+									ui32PTIndex));
+			PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: Page table entry value: 0x%08lX", pui32Tmp[ui32PTIndex]));
+		}
+
+
+		PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+		pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+								| SGX_MMU_PTE_VALID;
+#else
+
+		pui32Tmp[ui32PTIndex] = 0;
+#endif
+
+		CheckPT(ppsPTInfoList[0]);
+
+
+		sTmpDevVAddr.uiAddr += uPageSize;
+	}
+
+	MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->psDevInfo);
+
+#if defined(PDUMP)
+	MMU_PDumpPageTables (psMMUHeap, sDevVAddr, uPageSize*ui32PageCount, IMG_TRUE, hUniqueTag);
+#endif
+}
+
+
+IMG_DEV_PHYADDR
+MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr)
+{
+	IMG_UINT32 *pui32PageTable;
+	IMG_UINT32 ui32Index;
+	IMG_DEV_PHYADDR sDevPAddr;
+	MMU_PT_INFO **ppsPTInfoList;
+
+
+	ui32Index = sDevVPageAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+	ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
+	if (!ppsPTInfoList[0])
+	{
+		PVR_DPF((PVR_DBG_ERROR,"MMU_GetPhysPageAddr: Not mapped in at 0x%08x", sDevVPageAddr.uiAddr));
+		sDevPAddr.uiAddr = 0;
+		return sDevPAddr;
+	}
+
+
+	ui32Index = (sDevVPageAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+
+	pui32PageTable = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+
+	sDevPAddr.uiAddr = pui32PageTable[ui32Index];
+
+
+	sDevPAddr.uiAddr &= ~(pMMUHeap->ui32DataPageMask>>SGX_MMU_PTE_ADDR_ALIGNSHIFT);
+
+
+	sDevPAddr.uiAddr <<= SGX_MMU_PTE_ADDR_ALIGNSHIFT;
+
+	return sDevPAddr;
+}
+
+
+IMG_DEV_PHYADDR MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext)
+{
+	return (pMMUContext->sPDDevPAddr);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetPhysPageAddrKM (IMG_HANDLE hDevMemHeap,
+								   IMG_DEV_VIRTADDR sDevVAddr,
+								   IMG_DEV_PHYADDR *pDevPAddr,
+								   IMG_CPU_PHYADDR *pCpuPAddr)
+{
+	MMU_HEAP *pMMUHeap;
+	IMG_DEV_PHYADDR DevPAddr;
+
+
+
+	pMMUHeap = (MMU_HEAP*)BM_GetMMUHeap(hDevMemHeap);
+
+	DevPAddr = MMU_GetPhysPageAddr(pMMUHeap, sDevVAddr);
+	pCpuPAddr->uiAddr = DevPAddr.uiAddr;
+	pDevPAddr->uiAddr = DevPAddr.uiAddr;
+
+	return (pDevPAddr->uiAddr != 0) ? PVRSRV_OK : PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+
+PVRSRV_ERROR SGXGetMMUPDAddrKM(IMG_HANDLE		hDevCookie,
+								IMG_HANDLE 		hDevMemContext,
+								IMG_DEV_PHYADDR *psPDDevPAddr)
+{
+	if (!hDevCookie || !hDevMemContext || !psPDDevPAddr)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+
+	*psPDDevPAddr = ((BM_CONTEXT*)hDevMemContext)->psMMUContext->sPDDevPAddr;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+	PVRSRV_ERROR eError;
+	SYS_DATA *psSysData;
+	RA_ARENA *psLocalDevMemArena;
+	IMG_HANDLE hOSMemHandle = IMG_NULL;
+	IMG_BYTE *pui8MemBlock = IMG_NULL;
+	IMG_SYS_PHYADDR sMemBlockSysPAddr;
+	IMG_CPU_PHYADDR sMemBlockCpuPAddr;
+
+	SysAcquireData(&psSysData);
+
+	psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+	if(psLocalDevMemArena == IMG_NULL)
+	{
+
+		eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+						      3 * SGX_MMU_PAGE_SIZE,
+						      SGX_MMU_PAGE_SIZE,
+						      (IMG_VOID **)&pui8MemBlock,
+						      &hOSMemHandle);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR call to OSAllocPages failed"));
+			return eError;
+		}
+
+
+		if(pui8MemBlock)
+		{
+			sMemBlockCpuPAddr = OSMapLinToCPUPhys(pui8MemBlock);
+		}
+		else
+		{
+
+			sMemBlockCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, 0);
+		}
+	}
+	else
+	{
+
+
+		if(RA_Alloc(psLocalDevMemArena,
+					3 * SGX_MMU_PAGE_SIZE,
+					IMG_NULL,
+					IMG_NULL,
+					0,
+					SGX_MMU_PAGE_SIZE,
+					0,
+					&(sMemBlockSysPAddr.uiAddr)) != IMG_TRUE)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR call to RA_Alloc failed"));
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		}
+
+
+		sMemBlockCpuPAddr = SysSysPAddrToCpuPAddr(sMemBlockSysPAddr);
+		pui8MemBlock = OSMapPhysToLin(sMemBlockCpuPAddr,
+									  SGX_MMU_PAGE_SIZE * 3,
+									  PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+									  &hOSMemHandle);
+		if(!pui8MemBlock)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR failed to map page tables"));
+			return PVRSRV_ERROR_BAD_MAPPING;
+		}
+	}
+
+	psDevInfo->hBIFResetPDOSMemHandle = hOSMemHandle;
+	psDevInfo->sBIFResetPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sMemBlockCpuPAddr);
+	psDevInfo->sBIFResetPTDevPAddr.uiAddr = psDevInfo->sBIFResetPDDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+	psDevInfo->sBIFResetPageDevPAddr.uiAddr = psDevInfo->sBIFResetPTDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+
+
+	psDevInfo->pui32BIFResetPD = (IMG_UINT32 *)pui8MemBlock;
+	psDevInfo->pui32BIFResetPT = (IMG_UINT32 *)(pui8MemBlock + SGX_MMU_PAGE_SIZE);
+
+
+	OSMemSet(psDevInfo->pui32BIFResetPD, 0, SGX_MMU_PAGE_SIZE);
+	OSMemSet(psDevInfo->pui32BIFResetPT, 0, SGX_MMU_PAGE_SIZE);
+
+	OSMemSet(pui8MemBlock + (2 * SGX_MMU_PAGE_SIZE), 0xDB, SGX_MMU_PAGE_SIZE);
+
+	return PVRSRV_OK;
+}
+
+IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+	SYS_DATA *psSysData;
+	RA_ARENA *psLocalDevMemArena;
+	IMG_SYS_PHYADDR sPDSysPAddr;
+
+	SysAcquireData(&psSysData);
+
+	psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+	if(psLocalDevMemArena == IMG_NULL)
+	{
+		OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+					3 * SGX_MMU_PAGE_SIZE,
+					psDevInfo->pui32BIFResetPD,
+					psDevInfo->hBIFResetPDOSMemHandle);
+	}
+	else
+	{
+		OSUnMapPhysToLin(psDevInfo->pui32BIFResetPD,
+                         3 * SGX_MMU_PAGE_SIZE,
+                         PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+                         psDevInfo->hBIFResetPDOSMemHandle);
+
+		sPDSysPAddr = SysDevPAddrToSysPAddr(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->sBIFResetPDDevPAddr);
+		RA_Free(psLocalDevMemArena, sPDSysPAddr.uiAddr, IMG_FALSE);
+	}
+}
+
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+PVRSRV_ERROR WorkaroundBRN22997Alloc(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+	PVRSRV_ERROR eError;
+	SYS_DATA *psSysData;
+	RA_ARENA *psLocalDevMemArena;
+	IMG_HANDLE hPTPageOSMemHandle = IMG_NULL;
+	IMG_HANDLE hPDPageOSMemHandle = IMG_NULL;
+	IMG_UINT32 *pui32PD = IMG_NULL;
+	IMG_UINT32 *pui32PT = IMG_NULL;
+	IMG_CPU_PHYADDR sCpuPAddr;
+	IMG_DEV_PHYADDR sPTDevPAddr;
+	IMG_DEV_PHYADDR sPDDevPAddr;
+
+	SysAcquireData(&psSysData);
+
+	psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+	if(psLocalDevMemArena == IMG_NULL)
+	{
+
+		eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+						   SGX_MMU_PAGE_SIZE,
+						   SGX_MMU_PAGE_SIZE,
+						   (IMG_VOID **)&pui32PT,
+						   &hPTPageOSMemHandle);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to OSAllocPages failed"));
+			return eError;
+		}
+
+		eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+						   SGX_MMU_PAGE_SIZE,
+						   SGX_MMU_PAGE_SIZE,
+						   (IMG_VOID **)&pui32PD,
+						   &hPDPageOSMemHandle);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to OSAllocPages failed"));
+			return eError;
+		}
+
+
+		if(pui32PT)
+        {
+            sCpuPAddr = OSMapLinToCPUPhys(pui32PT);
+        }
+        else
+        {
+
+            sCpuPAddr = OSMemHandleToCpuPAddr(hPTPageOSMemHandle, 0);
+        }
+		sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+		if(pui32PD)
+        {
+            sCpuPAddr = OSMapLinToCPUPhys(pui32PD);
+        }
+        else
+        {
+
+            sCpuPAddr = OSMemHandleToCpuPAddr(hPDPageOSMemHandle, 0);
+        }
+		sPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+	}
+	else
+	{
+
+
+		if(RA_Alloc(psLocalDevMemArena,
+					SGX_MMU_PAGE_SIZE * 2,
+					IMG_NULL,
+					IMG_NULL,
+					0,
+					SGX_MMU_PAGE_SIZE,
+					0,
+					&(psDevInfo->sBRN22997SysPAddr.uiAddr))!= IMG_TRUE)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to RA_Alloc failed"));
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		}
+
+
+		sCpuPAddr = SysSysPAddrToCpuPAddr(psDevInfo->sBRN22997SysPAddr);
+		pui32PT = OSMapPhysToLin(sCpuPAddr,
+								SGX_MMU_PAGE_SIZE * 2,
+                                PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+								&hPTPageOSMemHandle);
+		if(!pui32PT)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR failed to map page tables"));
+			return PVRSRV_ERROR_BAD_MAPPING;
+		}
+
+
+		sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+		pui32PD = pui32PT + 1024;
+		sPDDevPAddr.uiAddr = sPTDevPAddr.uiAddr + 4096;
+	}
+
+	OSMemSet(pui32PD, 0, SGX_MMU_PAGE_SIZE);
+	OSMemSet(pui32PT, 0, SGX_MMU_PAGE_SIZE);
+
+
+	PDUMPMALLOCPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, pui32PD, SGX_MMU_PAGE_SIZE, PDUMP_PD_UNIQUETAG);
+	PDUMPMALLOCPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, pui32PT, SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+	PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+	PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+	psDevInfo->hBRN22997PTPageOSMemHandle = hPTPageOSMemHandle;
+	psDevInfo->hBRN22997PDPageOSMemHandle = hPDPageOSMemHandle;
+	psDevInfo->sBRN22997PTDevPAddr = sPTDevPAddr;
+	psDevInfo->sBRN22997PDDevPAddr = sPDDevPAddr;
+	psDevInfo->pui32BRN22997PD = pui32PD;
+	psDevInfo->pui32BRN22997PT = pui32PT;
+
+	return PVRSRV_OK;
+}
+
+
+IMG_VOID WorkaroundBRN22997ReadHostPort(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+	IMG_UINT32 *pui32PD = psDevInfo->pui32BRN22997PD;
+	IMG_UINT32 *pui32PT = psDevInfo->pui32BRN22997PT;
+	IMG_UINT32 ui32PDIndex;
+	IMG_UINT32 ui32PTIndex;
+	IMG_DEV_VIRTADDR sDevVAddr;
+	volatile IMG_UINT32 *pui32HostPort;
+	IMG_UINT32 ui32BIFCtrl;
+
+
+
+
+	pui32HostPort = (volatile IMG_UINT32*)(((IMG_UINT8*)psDevInfo->pvHostPortBaseKM) + SYS_SGX_HOSTPORT_BRN23030_OFFSET);
+
+
+	sDevVAddr.uiAddr = SYS_SGX_HOSTPORT_BASE_DEVVADDR + SYS_SGX_HOSTPORT_BRN23030_OFFSET;
+
+	ui32PDIndex = (sDevVAddr.uiAddr & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+	ui32PTIndex = (sDevVAddr.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+
+	pui32PD[ui32PDIndex] = (psDevInfo->sBRN22997PTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+							| SGX_MMU_PDE_VALID;
+
+	pui32PT[ui32PTIndex] = (psDevInfo->sBRN22997PTDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+							| SGX_MMU_PTE_VALID;
+
+	PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+	PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0,
+				 psDevInfo->sBRN22997PDDevPAddr.uiAddr);
+	PDUMPPDREG(EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sBRN22997PDDevPAddr.uiAddr, PDUMP_PD_UNIQUETAG);
+
+
+	ui32BIFCtrl = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL);
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+	PDUMPREG(EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+	PDUMPREG(EUR_CR_BIF_CTRL, ui32BIFCtrl);
+
+
+	if (pui32HostPort)
+	{
+
+		IMG_UINT32 ui32Tmp;
+		ui32Tmp = *pui32HostPort;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR,"Host Port not present for BRN22997 workaround"));
+	}
+
+
+
+
+
+
+
+	PDUMPCOMMENT("RDW :SGXMEM:v4:%08lX\r\n", sDevVAddr.uiAddr);
+
+    PDUMPCOMMENT("SAB :SGXMEM:v4:%08lX 4 0 hostport.bin", sDevVAddr.uiAddr);
+
+
+	pui32PD[ui32PDIndex] = 0;
+	pui32PT[ui32PTIndex] = 0;
+
+
+	PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+	PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+	PDUMPREG(EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+	PDUMPREG(EUR_CR_BIF_CTRL, ui32BIFCtrl);
+}
+
+
+IMG_VOID WorkaroundBRN22997Free(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+	SYS_DATA *psSysData;
+	RA_ARENA *psLocalDevMemArena;
+
+	SysAcquireData(&psSysData);
+
+	psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+	PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->pui32BRN22997PD, SGX_MMU_PAGE_SIZE, PDUMP_PD_UNIQUETAG);
+	PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->pui32BRN22997PT, SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+
+
+	if(psLocalDevMemArena == IMG_NULL)
+	{
+		if (psDevInfo->pui32BRN22997PD != IMG_NULL)
+		{
+			OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+						  SGX_MMU_PAGE_SIZE,
+						  psDevInfo->pui32BRN22997PD,
+						  psDevInfo->hBRN22997PDPageOSMemHandle);
+		}
+
+		if (psDevInfo->pui32BRN22997PT != IMG_NULL)
+		{
+			OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+						  SGX_MMU_PAGE_SIZE,
+						  psDevInfo->pui32BRN22997PT,
+						  psDevInfo->hBRN22997PTPageOSMemHandle);
+		}
+	}
+	else
+	{
+		if (psDevInfo->pui32BRN22997PT != IMG_NULL)
+		{
+			OSUnMapPhysToLin(psDevInfo->pui32BRN22997PT,
+				 SGX_MMU_PAGE_SIZE * 2,
+				 PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+				 psDevInfo->hBRN22997PTPageOSMemHandle);
+
+
+			RA_Free(psLocalDevMemArena, psDevInfo->sBRN22997SysPAddr.uiAddr, IMG_FALSE);
+		}
+	}
+}
+#endif
+
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_ERROR eError;
+	SYS_DATA *psSysData;
+	RA_ARENA *psLocalDevMemArena;
+	IMG_HANDLE hPTPageOSMemHandle = IMG_NULL;
+	IMG_UINT32 *pui32PD;
+	IMG_UINT32 *pui32PT = IMG_NULL;
+	IMG_CPU_PHYADDR sCpuPAddr;
+	IMG_DEV_PHYADDR sPTDevPAddr;
+	PVRSRV_SGXDEV_INFO *psDevInfo;
+	IMG_UINT32 ui32PDIndex;
+	IMG_UINT32 ui32PTIndex;
+
+	psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+	pui32PD = (IMG_UINT32*)psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->pvPDCpuVAddr;
+
+	SysAcquireData(&psSysData);
+
+	psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+	if(psLocalDevMemArena == IMG_NULL)
+	{
+
+		eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+						   SGX_MMU_PAGE_SIZE,
+						   SGX_MMU_PAGE_SIZE,
+						   (IMG_VOID **)&pui32PT,
+						   &hPTPageOSMemHandle);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_MapExtSystemCacheRegs: ERROR call to OSAllocPages failed"));
+			return eError;
+		}
+
+
+		if(pui32PT)
+        {
+            sCpuPAddr = OSMapLinToCPUPhys(pui32PT);
+        }
+        else
+        {
+
+            sCpuPAddr = OSMemHandleToCpuPAddr(hPTPageOSMemHandle, 0);
+        }
+		sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+	}
+	else
+	{
+		IMG_SYS_PHYADDR sSysPAddr;
+
+
+		if(RA_Alloc(psLocalDevMemArena,
+					SGX_MMU_PAGE_SIZE,
+					IMG_NULL,
+					IMG_NULL,
+					0,
+					SGX_MMU_PAGE_SIZE,
+					0,
+					&(sSysPAddr.uiAddr))!= IMG_TRUE)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_MapExtSystemCacheRegs: ERROR call to RA_Alloc failed"));
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		}
+
+
+		sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+		pui32PT = OSMapPhysToLin(sCpuPAddr,
+								SGX_MMU_PAGE_SIZE,
+                                PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+								&hPTPageOSMemHandle);
+		if(!pui32PT)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_MapExtSystemCacheRegs: ERROR failed to map page tables"));
+			return PVRSRV_ERROR_BAD_MAPPING;
+		}
+
+
+		sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+
+		psDevInfo->sExtSystemCacheRegsPTSysPAddr = sSysPAddr;
+	}
+
+	OSMemSet(pui32PT, 0, SGX_MMU_PAGE_SIZE);
+
+	ui32PDIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+	ui32PTIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+
+	pui32PD[ui32PDIndex] = (sPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+							| SGX_MMU_PDE_VALID;
+
+	pui32PT[ui32PTIndex] = (psDevInfo->sExtSysCacheRegsDevPBase.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+							| SGX_MMU_PTE_VALID;
+
+
+	PDUMPMALLOCPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, pui32PT, SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+	PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+	PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+
+	psDevInfo->pui32ExtSystemCacheRegsPT = pui32PT;
+	psDevInfo->hExtSystemCacheRegsPTPageOSMemHandle = hPTPageOSMemHandle;
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	SYS_DATA *psSysData;
+	RA_ARENA *psLocalDevMemArena;
+	PVRSRV_SGXDEV_INFO *psDevInfo;
+	IMG_UINT32 ui32PDIndex;
+	IMG_UINT32 *pui32PD;
+
+	psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+	pui32PD = (IMG_UINT32*)psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->pvPDCpuVAddr;
+
+	SysAcquireData(&psSysData);
+
+	psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+	ui32PDIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+	pui32PD[ui32PDIndex] = 0;
+
+	PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+	PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->pui32ExtSystemCacheRegsPT, SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+
+
+	if(psLocalDevMemArena == IMG_NULL)
+	{
+		if (psDevInfo->pui32ExtSystemCacheRegsPT != IMG_NULL)
+		{
+			OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+						  SGX_MMU_PAGE_SIZE,
+						  psDevInfo->pui32ExtSystemCacheRegsPT,
+						  psDevInfo->hExtSystemCacheRegsPTPageOSMemHandle);
+		}
+	}
+	else
+	{
+		if (psDevInfo->pui32ExtSystemCacheRegsPT != IMG_NULL)
+		{
+			OSUnMapPhysToLin(psDevInfo->pui32ExtSystemCacheRegsPT,
+				 SGX_MMU_PAGE_SIZE,
+				 PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+				 psDevInfo->hExtSystemCacheRegsPTPageOSMemHandle);
+
+			RA_Free(psLocalDevMemArena, psDevInfo->sExtSystemCacheRegsPTSysPAddr.uiAddr, IMG_FALSE);
+		}
+	}
+
+	return PVRSRV_OK;
+}
+#endif
+
+
+#if PAGE_TEST
+static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr)
+{
+	volatile IMG_UINT32 ui32WriteData;
+	volatile IMG_UINT32 ui32ReadData;
+	volatile IMG_UINT32 *pMem32 = (volatile IMG_UINT32 *)pMem;
+	IMG_INT n;
+	IMG_BOOL bOK=IMG_TRUE;
+
+	ui32WriteData = 0xffffffff;
+
+	for (n=0; n<1024; n++)
+	{
+		pMem32[n] = ui32WriteData;
+		ui32ReadData = pMem32[n];
+
+		if (ui32WriteData != ui32ReadData)
+		{
+
+			PVR_DPF ((PVR_DBG_ERROR, "Error - memory page test failed at device phys address 0x%08X", sDevPAddr.uiAddr + (n<<2) ));
+			PVR_DBG_BREAK;
+			bOK = IMG_FALSE;
+		}
+	}
+
+	ui32WriteData = 0;
+
+	for (n=0; n<1024; n++)
+	{
+		pMem32[n] = ui32WriteData;
+		ui32ReadData = pMem32[n];
+
+		if (ui32WriteData != ui32ReadData)
+		{
+
+			PVR_DPF ((PVR_DBG_ERROR, "Error - memory page test failed at device phys address 0x%08X", sDevPAddr.uiAddr + (n<<2) ));
+			PVR_DBG_BREAK;
+			bOK = IMG_FALSE;
+		}
+	}
+
+	if (bOK)
+	{
+		PVR_DPF ((PVR_DBG_VERBOSE, "MMU Page 0x%08X is OK", sDevPAddr.uiAddr));
+	}
+	else
+	{
+		PVR_DPF ((PVR_DBG_VERBOSE, "MMU Page 0x%08X *** FAILED ***", sDevPAddr.uiAddr));
+	}
+}
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.h
new file mode 100644
index 0000000..287d4f3
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/mmu.h
@@ -0,0 +1,135 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _MMU_H_
+#define _MMU_H_
+
+#include "sgxinfokm.h"
+
+PVRSRV_ERROR
+MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr);
+
+IMG_VOID
+MMU_Finalise (MMU_CONTEXT *psMMUContext);
+
+
+IMG_VOID
+MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap);
+
+MMU_HEAP *
+MMU_Create (MMU_CONTEXT *psMMUContext,
+			DEV_ARENA_DESCRIPTOR *psDevArena,
+			RA_ARENA **ppsVMArena);
+
+IMG_VOID
+MMU_Delete (MMU_HEAP *pMMU);
+
+IMG_BOOL
+MMU_Alloc (MMU_HEAP *pMMU,
+           IMG_SIZE_T uSize,
+           IMG_SIZE_T *pActualSize,
+           IMG_UINT32 uFlags,
+		   IMG_UINT32 uDevVAddrAlignment,
+           IMG_DEV_VIRTADDR *pDevVAddr);
+
+IMG_VOID
+MMU_Free (MMU_HEAP *pMMU,
+          IMG_DEV_VIRTADDR DevVAddr,
+		  IMG_UINT32 ui32Size);
+
+IMG_VOID
+MMU_Enable (MMU_HEAP *pMMU);
+
+IMG_VOID
+MMU_Disable (MMU_HEAP *pMMU);
+
+IMG_VOID
+MMU_MapPages (MMU_HEAP *pMMU,
+			  IMG_DEV_VIRTADDR devVAddr,
+			  IMG_SYS_PHYADDR SysPAddr,
+			  IMG_SIZE_T uSize,
+			  IMG_UINT32 ui32MemFlags,
+			  IMG_HANDLE hUniqueTag);
+
+IMG_VOID
+MMU_MapShadow (MMU_HEAP          * pMMU,
+               IMG_DEV_VIRTADDR    MapBaseDevVAddr,
+               IMG_SIZE_T          uSize,
+               IMG_CPU_VIRTADDR    CpuVAddr,
+               IMG_HANDLE          hOSMemHandle,
+               IMG_DEV_VIRTADDR  * pDevVAddr,
+               IMG_UINT32          ui32MemFlags,
+               IMG_HANDLE          hUniqueTag);
+
+IMG_VOID
+MMU_UnmapPages (MMU_HEAP *pMMU,
+             IMG_DEV_VIRTADDR dev_vaddr,
+             IMG_UINT32 ui32PageCount,
+             IMG_HANDLE hUniqueTag);
+
+IMG_VOID
+MMU_MapScatter (MMU_HEAP *pMMU,
+				IMG_DEV_VIRTADDR DevVAddr,
+				IMG_SYS_PHYADDR *psSysAddr,
+				IMG_SIZE_T uSize,
+				IMG_UINT32 ui32MemFlags,
+				IMG_HANDLE hUniqueTag);
+
+
+IMG_DEV_PHYADDR
+MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr);
+
+
+IMG_DEV_PHYADDR
+MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext);
+
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+IMG_VOID
+EnableHostAccess (MMU_CONTEXT *psMMUContext);
+
+
+IMG_VOID
+DisableHostAccess (MMU_CONTEXT *psMMUContext);
+#endif
+
+IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+PVRSRV_ERROR WorkaroundBRN22997Alloc(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+IMG_VOID WorkaroundBRN22997ReadHostPort(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+IMG_VOID WorkaroundBRN22997Free(PVRSRV_SGXDEV_INFO *psDevInfo);
+#endif
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/pb.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/pb.c
new file mode 100644
index 0000000..93f356d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/pb.c
@@ -0,0 +1,454 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "pvr_bridge_km.h"
+#include "pdump_km.h"
+#include "sgxutils.h"
+
+#ifndef __linux__
+#pragma message("TODO: Review use of OS_PAGEABLE vs OS_NON_PAGEABLE")
+#endif
+
+#include "lists.h"
+
+static IMPLEMENT_LIST_INSERT(PVRSRV_STUB_PBDESC)
+static IMPLEMENT_LIST_REMOVE(PVRSRV_STUB_PBDESC)
+
+static PRESMAN_ITEM psResItemCreateSharedPB = IMG_NULL;
+static PVRSRV_PER_PROCESS_DATA *psPerProcCreateSharedPB = IMG_NULL;
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param);
+static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param);
+
+IMG_EXPORT PVRSRV_ERROR
+SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+					  IMG_HANDLE 				hDevCookie,
+					  IMG_BOOL 				bLockOnFailure,
+					  IMG_UINT32 				ui32TotalPBSize,
+					  IMG_HANDLE 				*phSharedPBDesc,
+					  PVRSRV_KERNEL_MEM_INFO 	**ppsSharedPBDescKernelMemInfo,
+					  PVRSRV_KERNEL_MEM_INFO 	**ppsHWPBDescKernelMemInfo,
+					  PVRSRV_KERNEL_MEM_INFO 	**ppsBlockKernelMemInfo,
+					  PVRSRV_KERNEL_MEM_INFO 	**ppsHWBlockKernelMemInfo,
+					  PVRSRV_KERNEL_MEM_INFO 	***pppsSharedPBDescSubKernelMemInfos,
+					  IMG_UINT32				*ui32SharedPBDescSubKernelMemInfosCount)
+{
+	PVRSRV_STUB_PBDESC *psStubPBDesc;
+	PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos=IMG_NULL;
+	PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+	PVRSRV_ERROR eError;
+
+	psSGXDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+	psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
+	if (psStubPBDesc != IMG_NULL)
+	{
+		IMG_UINT32 i;
+		PRESMAN_ITEM psResItem;
+
+		if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize)
+		{
+			PVR_DPF((PVR_DBG_WARNING,
+					"SGXFindSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored",
+					ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize));
+		}
+
+		if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					  sizeof(PVRSRV_KERNEL_MEM_INFO *)
+						* psStubPBDesc->ui32SubKernelMemInfosCount,
+					  (IMG_VOID **)&ppsSharedPBDescSubKernelMemInfos,
+					  IMG_NULL,
+					  "Array of Kernel Memory Info") != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: OSAllocMem failed"));
+
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+			goto ExitNotFound;
+		}
+
+		psResItem = ResManRegisterRes(psPerProc->hResManContext,
+									  RESMAN_TYPE_SHARED_PB_DESC,
+									  psStubPBDesc,
+									  0,
+									  &SGXCleanupSharedPBDescCallback);
+
+		if (psResItem == IMG_NULL)
+		{
+			OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					  sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDesc->ui32SubKernelMemInfosCount,
+					  ppsSharedPBDescSubKernelMemInfos,
+					  0);
+
+
+			PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed"));
+
+			eError = PVRSRV_ERROR_GENERIC;
+			goto ExitNotFound;
+		}
+
+		*ppsSharedPBDescKernelMemInfo = psStubPBDesc->psSharedPBDescKernelMemInfo;
+		*ppsHWPBDescKernelMemInfo = psStubPBDesc->psHWPBDescKernelMemInfo;
+		*ppsBlockKernelMemInfo = psStubPBDesc->psBlockKernelMemInfo;
+		*ppsHWBlockKernelMemInfo = psStubPBDesc->psHWBlockKernelMemInfo;
+
+		*ui32SharedPBDescSubKernelMemInfosCount =
+			psStubPBDesc->ui32SubKernelMemInfosCount;
+
+		*pppsSharedPBDescSubKernelMemInfos = ppsSharedPBDescSubKernelMemInfos;
+
+		for(i=0; i<psStubPBDesc->ui32SubKernelMemInfosCount; i++)
+		{
+			ppsSharedPBDescSubKernelMemInfos[i] =
+				psStubPBDesc->ppsSubKernelMemInfos[i];
+		}
+
+		psStubPBDesc->ui32RefCount++;
+		*phSharedPBDesc = (IMG_HANDLE)psResItem;
+		return PVRSRV_OK;
+	}
+
+	eError = PVRSRV_OK;
+	if (bLockOnFailure)
+	{
+		if (psResItemCreateSharedPB == IMG_NULL)
+		{
+			psResItemCreateSharedPB = ResManRegisterRes(psPerProc->hResManContext,
+				  RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
+				  psPerProc,
+				  0,
+				  &SGXCleanupSharedPBDescCreateLockCallback);
+
+			if (psResItemCreateSharedPB == IMG_NULL)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed"));
+
+				eError = PVRSRV_ERROR_GENERIC;
+				goto ExitNotFound;
+			}
+			PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL);
+			psPerProcCreateSharedPB = psPerProc;
+		}
+		else
+		{
+			 eError = PVRSRV_ERROR_PROCESSING_BLOCKED;
+		}
+	}
+ExitNotFound:
+	*phSharedPBDesc = IMG_NULL;
+
+	return eError;
+}
+
+
+static PVRSRV_ERROR
+SGXCleanupSharedPBDescKM(PVRSRV_STUB_PBDESC *psStubPBDescIn)
+{
+
+	IMG_UINT32 i;
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE*)psStubPBDescIn->hDevCookie;
+
+
+
+
+	psStubPBDescIn->ui32RefCount--;
+	if (psStubPBDescIn->ui32RefCount == 0)
+	{
+		List_PVRSRV_STUB_PBDESC_Remove(psStubPBDescIn);
+		for(i=0 ; i<psStubPBDescIn->ui32SubKernelMemInfosCount; i++)
+		{
+
+			PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie,
+								  psStubPBDescIn->ppsSubKernelMemInfos[i]);
+		}
+
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDescIn->ui32SubKernelMemInfosCount,
+				  psStubPBDescIn->ppsSubKernelMemInfos,
+				  0);
+		psStubPBDescIn->ppsSubKernelMemInfos = IMG_NULL;
+
+		PVRSRVFreeSharedSysMemoryKM(psStubPBDescIn->psBlockKernelMemInfo);
+
+		PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, psStubPBDescIn->psHWBlockKernelMemInfo);
+
+		PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, psStubPBDescIn->psHWPBDescKernelMemInfo);
+
+		PVRSRVFreeSharedSysMemoryKM(psStubPBDescIn->psSharedPBDescKernelMemInfo);
+
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_STUB_PBDESC),
+				  psStubPBDescIn,
+				  0);
+
+
+
+		SGXCleanupRequest(psDeviceNode,
+						  IMG_NULL,
+						  PVRSRV_CLEANUPCMD_PB);
+	}
+	return PVRSRV_OK;
+
+}
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+	PVRSRV_STUB_PBDESC *psStubPBDesc = (PVRSRV_STUB_PBDESC *)pvParam;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+	return SGXCleanupSharedPBDescKM(psStubPBDesc);
+}
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+#ifdef DEBUG
+	PVRSRV_PER_PROCESS_DATA *psPerProc = (PVRSRV_PER_PROCESS_DATA *)pvParam;
+	PVR_ASSERT(psPerProc == psPerProcCreateSharedPB);
+#else
+	PVR_UNREFERENCED_PARAMETER(pvParam);
+#endif
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+	psPerProcCreateSharedPB = IMG_NULL;
+	psResItemCreateSharedPB = IMG_NULL;
+
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc)
+{
+	PVR_ASSERT(hSharedPBDesc != IMG_NULL);
+
+	return ResManFreeResByPtr(hSharedPBDesc);
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+					 IMG_HANDLE					hDevCookie,
+					 PVRSRV_KERNEL_MEM_INFO		*psSharedPBDescKernelMemInfo,
+					 PVRSRV_KERNEL_MEM_INFO		*psHWPBDescKernelMemInfo,
+					 PVRSRV_KERNEL_MEM_INFO		*psBlockKernelMemInfo,
+					 PVRSRV_KERNEL_MEM_INFO		*psHWBlockKernelMemInfo,
+					 IMG_UINT32					ui32TotalPBSize,
+					 IMG_HANDLE					*phSharedPBDesc,
+					 PVRSRV_KERNEL_MEM_INFO		**ppsSharedPBDescSubKernelMemInfos,
+					 IMG_UINT32					ui32SharedPBDescSubKernelMemInfosCount)
+{
+	PVRSRV_STUB_PBDESC *psStubPBDesc=IMG_NULL;
+	PVRSRV_ERROR eRet = PVRSRV_ERROR_GENERIC;
+	IMG_UINT32 i;
+	PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+	PRESMAN_ITEM psResItem;
+
+
+	if (psPerProcCreateSharedPB != psPerProc)
+	{
+		goto NoAdd;
+	}
+	else
+	{
+		PVR_ASSERT(psResItemCreateSharedPB != IMG_NULL);
+
+		ResManFreeResByPtr(psResItemCreateSharedPB);
+
+		PVR_ASSERT(psResItemCreateSharedPB == IMG_NULL);
+		PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL);
+	}
+
+	psSGXDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+	psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
+	if (psStubPBDesc != IMG_NULL)
+	{
+		if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize)
+		{
+			PVR_DPF((PVR_DBG_WARNING,
+					"SGXAddSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored",
+					ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize));
+
+		}
+
+
+		psResItem = ResManRegisterRes(psPerProc->hResManContext,
+									  RESMAN_TYPE_SHARED_PB_DESC,
+									  psStubPBDesc,
+									  0,
+									  &SGXCleanupSharedPBDescCallback);
+		if (psResItem == IMG_NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+				"SGXAddSharedPBDescKM: "
+				"Failed to register existing shared "
+				"PBDesc with the resource manager"));
+			goto NoAddKeepPB;
+		}
+
+
+		psStubPBDesc->ui32RefCount++;
+
+		*phSharedPBDesc = (IMG_HANDLE)psResItem;
+		eRet = PVRSRV_OK;
+		goto NoAddKeepPB;
+	}
+
+	if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_STUB_PBDESC),
+				  (IMG_VOID **)&psStubPBDesc,
+				  0,
+				  "Stub Parameter Buffer Description") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: Failed to alloc "
+					"StubPBDesc"));
+		eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto NoAdd;
+	}
+
+
+	psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL;
+
+	if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_KERNEL_MEM_INFO *)
+				  * ui32SharedPBDescSubKernelMemInfosCount,
+				  (IMG_VOID **)&psStubPBDesc->ppsSubKernelMemInfos,
+				  0,
+				  "Array of Kernel Memory Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+				 "Failed to alloc "
+				 "StubPBDesc->ppsSubKernelMemInfos"));
+		eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto NoAdd;
+	}
+
+	if(PVRSRVDissociateMemFromResmanKM(psSharedPBDescKernelMemInfo)
+	   != PVRSRV_OK)
+	{
+		goto NoAdd;
+	}
+
+	if(PVRSRVDissociateMemFromResmanKM(psHWPBDescKernelMemInfo)
+	   != PVRSRV_OK)
+	{
+		goto NoAdd;
+	}
+
+	if(PVRSRVDissociateMemFromResmanKM(psBlockKernelMemInfo)
+	   != PVRSRV_OK)
+	{
+		goto NoAdd;
+	}
+
+	if(PVRSRVDissociateMemFromResmanKM(psHWBlockKernelMemInfo)
+	   != PVRSRV_OK)
+	{
+		goto NoAdd;
+	}
+
+	psStubPBDesc->ui32RefCount = 1;
+	psStubPBDesc->ui32TotalPBSize = ui32TotalPBSize;
+	psStubPBDesc->psSharedPBDescKernelMemInfo = psSharedPBDescKernelMemInfo;
+	psStubPBDesc->psHWPBDescKernelMemInfo = psHWPBDescKernelMemInfo;
+	psStubPBDesc->psBlockKernelMemInfo = psBlockKernelMemInfo;
+	psStubPBDesc->psHWBlockKernelMemInfo = psHWBlockKernelMemInfo;
+
+	psStubPBDesc->ui32SubKernelMemInfosCount =
+		ui32SharedPBDescSubKernelMemInfosCount;
+	for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++)
+	{
+		psStubPBDesc->ppsSubKernelMemInfos[i] = ppsSharedPBDescSubKernelMemInfos[i];
+		if(PVRSRVDissociateMemFromResmanKM(ppsSharedPBDescSubKernelMemInfos[i])
+		   != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+					 "Failed to dissociate shared PBDesc "
+					 "from process"));
+			goto NoAdd;
+		}
+	}
+
+	psResItem = ResManRegisterRes(psPerProc->hResManContext,
+								  RESMAN_TYPE_SHARED_PB_DESC,
+								  psStubPBDesc,
+								  0,
+								  &SGXCleanupSharedPBDescCallback);
+	if (psResItem == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+					 "Failed to register shared PBDesc "
+					 " with the resource manager"));
+		goto NoAdd;
+	}
+	psStubPBDesc->hDevCookie = hDevCookie;
+
+
+	List_PVRSRV_STUB_PBDESC_Insert(&(psSGXDevInfo->psStubPBDescListKM),
+									psStubPBDesc);
+
+	*phSharedPBDesc = (IMG_HANDLE)psResItem;
+
+	return PVRSRV_OK;
+
+NoAdd:
+	if(psStubPBDesc)
+	{
+		if(psStubPBDesc->ppsSubKernelMemInfos)
+		{
+			OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					  sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount,
+					  psStubPBDesc->ppsSubKernelMemInfos,
+					  0);
+			psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL;
+		}
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_STUB_PBDESC),
+				  psStubPBDesc,
+				  0);
+
+	}
+
+NoAddKeepPB:
+	for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++)
+	{
+		PVRSRVFreeDeviceMemKM(hDevCookie, ppsSharedPBDescSubKernelMemInfos[i]);
+	}
+
+	PVRSRVFreeSharedSysMemoryKM(psSharedPBDescKernelMemInfo);
+	PVRSRVFreeDeviceMemKM(hDevCookie, psHWPBDescKernelMemInfo);
+
+	PVRSRVFreeSharedSysMemoryKM(psBlockKernelMemInfo);
+	PVRSRVFreeDeviceMemKM(hDevCookie, psHWBlockKernelMemInfo);
+
+	return eRet;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h
new file mode 100644
index 0000000..bfc726f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h
@@ -0,0 +1,143 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__SGX_BRIDGE_KM_H__)
+#define __SGX_BRIDGE_KM_H__
+
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "sgx_bridge.h"
+#include "pvr_bridge.h"
+#include "perproc.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK *psKick);
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_IMPORT
+PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK *psKick);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle,
+						 SGX_CCB_KICK *psCCBKick);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetPhysPageAddrKM(IMG_HANDLE hDevMemHeap,
+								  IMG_DEV_VIRTADDR sDevVAddr,
+								  IMG_DEV_PHYADDR *pDevPAddr,
+								  IMG_CPU_PHYADDR *pCpuPAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV SGXGetMMUPDAddrKM(IMG_HANDLE		hDevCookie,
+											IMG_HANDLE		hDevMemContext,
+											IMG_DEV_PHYADDR	*psPDDevPAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE				hDevCookie,
+								SGX_CLIENT_INFO*	psClientInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO	*psDevInfo,
+							  SGX_MISC_INFO			*psMiscInfo,
+							  PVRSRV_DEVICE_NODE 	*psDeviceNode,
+							  IMG_HANDLE 			 hDevMemContext);
+
+#if defined(SUPPORT_SGX_HWPERF)
+IMG_IMPORT
+PVRSRV_ERROR SGXReadDiffCountersKM(IMG_HANDLE				hDevHandle,
+								   IMG_UINT32				ui32Reg,
+								   IMG_UINT32				*pui32Old,
+								   IMG_BOOL					bNew,
+								   IMG_UINT32				ui32New,
+								   IMG_UINT32				ui32NewReset,
+								   IMG_UINT32				ui32CountersReg,
+								   IMG_UINT32				ui32Reg2,
+								   IMG_BOOL					*pbActive,
+								   PVRSRV_SGXDEV_DIFF_INFO	*psDiffs);
+IMG_IMPORT
+PVRSRV_ERROR SGXReadHWPerfCBKM(IMG_HANDLE					hDevHandle,
+							   IMG_UINT32					ui32ArraySize,
+							   PVRSRV_SGX_HWPERF_CB_ENTRY	*psHWPerfCBData,
+							   IMG_UINT32					*pui32DataCount,
+							   IMG_UINT32					*pui32ClockSpeed,
+							   IMG_UINT32					*pui32HostTimeStamp);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO		*psDevInfo,
+									   PVRSRV_KERNEL_SYNC_INFO	*psSyncInfo,
+									   IMG_BOOL bWaitForComplete);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle,
+									SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR DevInitSGXPart2KM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+							   IMG_HANDLE hDevHandle,
+							   SGX_BRIDGE_INIT_INFO *psInitInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+					  IMG_HANDLE				hDevCookie,
+					  IMG_BOOL				bLockOnFailure,
+					  IMG_UINT32				ui32TotalPBSize,
+					  IMG_HANDLE				*phSharedPBDesc,
+					  PVRSRV_KERNEL_MEM_INFO	**ppsSharedPBDescKernelMemInfo,
+					  PVRSRV_KERNEL_MEM_INFO	**ppsHWPBDescKernelMemInfo,
+					  PVRSRV_KERNEL_MEM_INFO	**ppsBlockKernelMemInfo,
+					  PVRSRV_KERNEL_MEM_INFO	**ppsHWBlockKernelMemInfo,
+					  PVRSRV_KERNEL_MEM_INFO	***pppsSharedPBDescSubKernelMemInfos,
+					  IMG_UINT32				*ui32SharedPBDescSubKernelMemInfosCount);
+
+IMG_IMPORT PVRSRV_ERROR
+SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc);
+
+IMG_IMPORT PVRSRV_ERROR
+SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+					 IMG_HANDLE 				hDevCookie,
+					 PVRSRV_KERNEL_MEM_INFO		*psSharedPBDescKernelMemInfo,
+					 PVRSRV_KERNEL_MEM_INFO		*psHWPBDescKernelMemInfo,
+					 PVRSRV_KERNEL_MEM_INFO		*psBlockKernelMemInfo,
+					 PVRSRV_KERNEL_MEM_INFO		*psHWBlockKernelMemInfo,
+					 IMG_UINT32					ui32TotalPBSize,
+					 IMG_HANDLE					*phSharedPBDesc,
+					 PVRSRV_KERNEL_MEM_INFO		**psSharedPBDescSubKernelMemInfos,
+					 IMG_UINT32					ui32SharedPBDescSubKernelMemInfosCount);
+
+
+IMG_IMPORT PVRSRV_ERROR
+SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
+						SGX_INTERNAL_DEVINFO *psSGXInternalDevInfo);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxconfig.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxconfig.h
new file mode 100644
index 0000000..58415d8
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxconfig.h
@@ -0,0 +1,161 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __SGXCONFIG_H__
+#define __SGXCONFIG_H__
+
+#include "sgxdefs.h"
+
+#define DEV_DEVICE_TYPE			PVRSRV_DEVICE_TYPE_SGX
+#define DEV_DEVICE_CLASS		PVRSRV_DEVICE_CLASS_3D
+
+#define DEV_MAJOR_VERSION		1
+#define DEV_MINOR_VERSION		0
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 32
+#if 0 /* ORIGIAL_SGX_MAP */
+	#if defined(SGX_FEATURE_2D_HARDWARE)
+	#define SGX_2D_HEAP_BASE					 0x00100000
+	#define SGX_2D_HEAP_SIZE					(0x08000000-0x00100000-0x00001000)
+	#else
+		#if defined(FIX_HW_BRN_26915)
+		#define SGX_CGBUFFER_HEAP_BASE					 0x00100000
+		#define SGX_CGBUFFER_HEAP_SIZE					(0x08000000-0x00100000-0x00001000)
+		#endif
+	#endif
+
+	#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+	#define SGX_GENERAL_MAPPING_HEAP_BASE		 0x08000000
+	#define SGX_GENERAL_MAPPING_HEAP_SIZE		(0x08000000-0x00001000)
+	#endif
+
+	#define SGX_GENERAL_HEAP_BASE				 0x10000000
+	#define SGX_GENERAL_HEAP_SIZE				(0xC8000000-0x00001000)
+#else /* EMGD Mapping */
+	/* Leave 0 - 0x10000000 (256MB) untouched */
+	#define SGX_2D_HEAP_BASE					 0x10000000
+	#define SGX_2D_HEAP_SIZE					(0x08000000-0x00001000)
+
+#if defined(SUPPORT_SGX_VIDEO_HEAP)
+
+	#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+	#define SGX_GENERAL_MAPPING_HEAP_BASE		 0x18000000
+	#define SGX_GENERAL_MAPPING_HEAP_SIZE		(0x30000000-0x00001000)
+	#endif
+
+	#define SGX_VIDEO_HEAP_BASE					 0x48000000
+	#define SGX_VIDEO_HEAP_SIZE					(0x18000000-0x00001000)
+
+	#define SGX_GENERAL_HEAP_BASE				 0x60000000
+	#define SGX_GENERAL_HEAP_SIZE				(0x78000000-0x00001000)
+
+#else
+
+	#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+	#define SGX_GENERAL_MAPPING_HEAP_BASE		 0x18000000
+	#define SGX_GENERAL_MAPPING_HEAP_SIZE		(0x08000000-0x00001000)
+	#endif
+
+	#define SGX_GENERAL_HEAP_BASE				 0x20000000
+	#define SGX_GENERAL_HEAP_SIZE				(0xB8000000-0x00001000)
+
+#endif
+
+#endif
+	#define SGX_3DPARAMETERS_HEAP_BASE			 0xD8000000
+	#define SGX_3DPARAMETERS_HEAP_SIZE			(0x10000000-0x00001000)
+
+	#define SGX_TADATA_HEAP_BASE				 0xE8000000
+	#define SGX_TADATA_HEAP_SIZE				(0x0D000000-0x00001000)
+
+	#define SGX_SYNCINFO_HEAP_BASE				 0xF5000000
+	#define SGX_SYNCINFO_HEAP_SIZE				(0x01000000-0x00001000)
+
+	#define SGX_PDSPIXEL_CODEDATA_HEAP_BASE		 0xF6000000
+	#define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE		(0x02000000-0x00001000)
+
+	#define SGX_KERNEL_CODE_HEAP_BASE			 0xF8000000
+	#define SGX_KERNEL_CODE_HEAP_SIZE			(0x00080000-0x00001000)
+
+	#define SGX_PDSVERTEX_CODEDATA_HEAP_BASE	 0xF8400000
+	#define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE	(0x01C00000-0x00001000)
+
+	#define SGX_KERNEL_DATA_HEAP_BASE		 	 0xFA000000
+	#define SGX_KERNEL_DATA_HEAP_SIZE			(0x05000000-0x00001000)
+
+	#define SGX_PIXELSHADER_HEAP_BASE			 0xFF000000
+	#define SGX_PIXELSHADER_HEAP_SIZE			(0x00500000-0x00001000)
+
+	#define SGX_VERTEXSHADER_HEAP_BASE			 0xFF800000
+	#define SGX_VERTEXSHADER_HEAP_SIZE			(0x00200000-0x00001000)
+
+
+	#define SGX_CORE_IDENTIFIED
+#endif
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 28
+	#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+	#define SGX_GENERAL_MAPPING_HEAP_BASE		 0x00001000
+	#define SGX_GENERAL_MAPPING_HEAP_SIZE		(0x01800000-0x00001000-0x00001000)
+	#endif
+
+	#define SGX_GENERAL_HEAP_BASE				 0x01800000
+	#define SGX_GENERAL_HEAP_SIZE				(0x07000000-0x00001000)
+
+	#define SGX_3DPARAMETERS_HEAP_BASE			 0x08800000
+	#define SGX_3DPARAMETERS_HEAP_SIZE			(0x04000000-0x00001000)
+
+	#define SGX_TADATA_HEAP_BASE				 0x0C800000
+	#define SGX_TADATA_HEAP_SIZE				(0x01000000-0x00001000)
+
+	#define SGX_SYNCINFO_HEAP_BASE				 0x0D800000
+	#define SGX_SYNCINFO_HEAP_SIZE				(0x00400000-0x00001000)
+
+	#define SGX_PDSPIXEL_CODEDATA_HEAP_BASE		 0x0DC00000
+	#define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE		(0x00800000-0x00001000)
+
+	#define SGX_KERNEL_CODE_HEAP_BASE			 0x0E400000
+	#define SGX_KERNEL_CODE_HEAP_SIZE			(0x00080000-0x00001000)
+
+	#define SGX_PDSVERTEX_CODEDATA_HEAP_BASE	 0x0E800000
+	#define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE	(0x00800000-0x00001000)
+
+	#define SGX_KERNEL_DATA_HEAP_BASE			 0x0F000000
+	#define SGX_KERNEL_DATA_HEAP_SIZE			(0x00400000-0x00001000)
+
+	#define SGX_PIXELSHADER_HEAP_BASE			 0x0F400000
+	#define SGX_PIXELSHADER_HEAP_SIZE			(0x00500000-0x00001000)
+
+	#define SGX_VERTEXSHADER_HEAP_BASE			 0x0FC00000
+	#define SGX_VERTEXSHADER_HEAP_SIZE			(0x00200000-0x00001000)
+
+
+	#define SGX_CORE_IDENTIFIED
+
+#endif
+
+#if !defined(SGX_CORE_IDENTIFIED)
+	#error "sgxconfig.h: ERROR: unspecified SGX Core version"
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxinfokm.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxinfokm.h
new file mode 100644
index 0000000..b4fd589
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxinfokm.h
@@ -0,0 +1,348 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __SGXINFOKM_H__
+#define __SGXINFOKM_H__
+
+#include "sgxdefs.h"
+#include "device.h"
+#include "power.h"
+#include "sysconfig.h"
+#include "sgxscript.h"
+#include "sgxinfo.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define		SGX_HOSTPORT_PRESENT			0x00000001UL
+
+
+typedef struct _PVRSRV_STUB_PBDESC_ PVRSRV_STUB_PBDESC;
+
+
+typedef struct _PVRSRV_SGX_CCB_INFO_ *PPVRSRV_SGX_CCB_INFO;
+
+typedef struct _PVRSRV_SGXDEV_INFO_
+{
+	PVRSRV_DEVICE_TYPE		eDeviceType;
+	PVRSRV_DEVICE_CLASS		eDeviceClass;
+
+	IMG_UINT8				ui8VersionMajor;
+	IMG_UINT8				ui8VersionMinor;
+	IMG_UINT32				ui32CoreConfig;
+	IMG_UINT32				ui32CoreFlags;
+
+
+	IMG_PVOID				pvRegsBaseKM;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+
+	IMG_PVOID				pvHostPortBaseKM;
+
+	IMG_UINT32				ui32HPSize;
+
+	IMG_SYS_PHYADDR			sHPSysPAddr;
+#endif
+
+
+	IMG_HANDLE				hRegMapping;
+
+
+	IMG_SYS_PHYADDR			sRegsPhysBase;
+
+	IMG_UINT32				ui32RegSize;
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+
+	IMG_UINT32				ui32ExtSysCacheRegsSize;
+
+	IMG_DEV_PHYADDR			sExtSysCacheRegsDevPBase;
+
+	IMG_UINT32				*pui32ExtSystemCacheRegsPT;
+
+	IMG_HANDLE				hExtSystemCacheRegsPTPageOSMemHandle;
+
+	IMG_SYS_PHYADDR			sExtSystemCacheRegsPTSysPAddr;
+#endif
+
+
+	IMG_UINT32				ui32CoreClockSpeed;
+	IMG_UINT32				ui32uKernelTimerClock;
+
+	PVRSRV_STUB_PBDESC		*psStubPBDescListKM;
+
+
+
+	IMG_DEV_PHYADDR			sKernelPDDevPAddr;
+
+	IMG_VOID				*pvDeviceMemoryHeap;
+	PPVRSRV_KERNEL_MEM_INFO	psKernelCCBMemInfo;
+	PVRSRV_SGX_KERNEL_CCB	*psKernelCCB;
+	PPVRSRV_SGX_CCB_INFO	psKernelCCBInfo;
+	PPVRSRV_KERNEL_MEM_INFO	psKernelCCBCtlMemInfo;
+	PVRSRV_SGX_CCB_CTL		*psKernelCCBCtl;
+	PPVRSRV_KERNEL_MEM_INFO psKernelCCBEventKickerMemInfo;
+	IMG_UINT32				*pui32KernelCCBEventKicker;
+#if defined(PDUMP)
+	IMG_UINT32				ui32KernelCCBEventKickerDumpVal;
+#endif
+	PVRSRV_KERNEL_MEM_INFO	*psKernelSGXMiscMemInfo;
+	IMG_UINT32				aui32HostKickAddr[SGXMKIF_CMD_MAX];
+#if defined(SGX_SUPPORT_HWPROFILING)
+	PPVRSRV_KERNEL_MEM_INFO psKernelHWProfilingMemInfo;
+#endif
+	IMG_UINT32				ui32KickTACounter;
+	IMG_UINT32				ui32KickTARenderCounter;
+#if defined(SUPPORT_SGX_HWPERF)
+	PPVRSRV_KERNEL_MEM_INFO		psKernelHWPerfCBMemInfo;
+	IMG_UINT32					ui32HWGroupRequested;
+	IMG_UINT32					ui32HWReset;
+#endif
+#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
+	PPVRSRV_KERNEL_MEM_INFO	psKernelEDMStatusBufferMemInfo;
+#endif
+#if defined(SGX_FEATURE_OVERLAPPED_SPM)
+	PPVRSRV_KERNEL_MEM_INFO	psKernelTmpRgnHeaderMemInfo;
+#endif
+#if defined(SGX_FEATURE_SPM_MODE_0)
+	PPVRSRV_KERNEL_MEM_INFO	psKernelTmpDPMStateMemInfo;
+#endif
+
+
+	IMG_UINT32				ui32ClientRefCount;
+
+
+	IMG_UINT32				ui32CacheControl;
+
+
+	IMG_UINT32				ui32ClientBuildOptions;
+
+
+	SGX_MISCINFO_STRUCT_SIZES	sSGXStructSizes;
+
+
+
+
+	IMG_VOID				*pvMMUContextList;
+
+
+	IMG_BOOL				bForcePTOff;
+
+	IMG_UINT32				ui32EDMTaskReg0;
+	IMG_UINT32				ui32EDMTaskReg1;
+
+	IMG_UINT32				ui32ClkGateStatusReg;
+	IMG_UINT32				ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+	IMG_UINT32				ui32MasterClkGateStatusReg;
+	IMG_UINT32				ui32MasterClkGateStatusMask;
+#endif
+	SGX_INIT_SCRIPTS		sScripts;
+
+
+	IMG_HANDLE 				hBIFResetPDOSMemHandle;
+	IMG_DEV_PHYADDR 		sBIFResetPDDevPAddr;
+	IMG_DEV_PHYADDR 		sBIFResetPTDevPAddr;
+	IMG_DEV_PHYADDR 		sBIFResetPageDevPAddr;
+	IMG_UINT32				*pui32BIFResetPD;
+	IMG_UINT32				*pui32BIFResetPT;
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+
+	IMG_HANDLE				hBRN22997PTPageOSMemHandle;
+	IMG_HANDLE				hBRN22997PDPageOSMemHandle;
+	IMG_DEV_PHYADDR 		sBRN22997PTDevPAddr;
+	IMG_DEV_PHYADDR 		sBRN22997PDDevPAddr;
+	IMG_UINT32				*pui32BRN22997PT;
+	IMG_UINT32				*pui32BRN22997PD;
+	IMG_SYS_PHYADDR 		sBRN22997SysPAddr;
+#endif
+
+#if defined(SUPPORT_HW_RECOVERY)
+
+	IMG_HANDLE				hTimer;
+
+	IMG_UINT32				ui32TimeStamp;
+#endif
+
+
+	IMG_UINT32				ui32NumResets;
+
+
+	PVRSRV_KERNEL_MEM_INFO			*psKernelSGXHostCtlMemInfo;
+	SGXMKIF_HOST_CTL				*psSGXHostCtl;
+
+
+	PVRSRV_KERNEL_MEM_INFO			*psKernelSGXTA3DCtlMemInfo;
+
+	IMG_UINT32				ui32Flags;
+
+	#if defined(PDUMP)
+	PVRSRV_SGX_PDUMP_CONTEXT	sPDContext;
+	#endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+	IMG_VOID				*pvDummyPTPageCpuVAddr;
+	IMG_DEV_PHYADDR			sDummyPTDevPAddr;
+	IMG_HANDLE				hDummyPTPageOSMemHandle;
+	IMG_VOID				*pvDummyDataPageCpuVAddr;
+	IMG_DEV_PHYADDR 		sDummyDataDevPAddr;
+	IMG_HANDLE				hDummyDataPageOSMemHandle;
+#endif
+
+	IMG_UINT32				asSGXDevData[SGX_MAX_DEV_DATA];
+
+} PVRSRV_SGXDEV_INFO;
+
+
+typedef struct _SGX_TIMING_INFORMATION_
+{
+	IMG_UINT32			ui32CoreClockSpeed;
+	IMG_UINT32			ui32HWRecoveryFreq;
+	IMG_BOOL			bEnableActivePM;
+	IMG_UINT32			ui32ActivePowManLatencyms;
+	IMG_UINT32			ui32uKernelFreq;
+} SGX_TIMING_INFORMATION;
+
+typedef struct _SGX_DEVICE_MAP_
+{
+	IMG_UINT32				ui32Flags;
+
+
+	IMG_SYS_PHYADDR			sRegsSysPBase;
+	IMG_CPU_PHYADDR			sRegsCpuPBase;
+	IMG_CPU_VIRTADDR		pvRegsCpuVBase;
+	IMG_UINT32				ui32RegsSize;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+	IMG_SYS_PHYADDR			sHPSysPBase;
+	IMG_CPU_PHYADDR			sHPCpuPBase;
+	IMG_UINT32				ui32HPSize;
+#endif
+
+
+	IMG_SYS_PHYADDR			sLocalMemSysPBase;
+	IMG_DEV_PHYADDR			sLocalMemDevPBase;
+	IMG_CPU_PHYADDR			sLocalMemCpuPBase;
+	IMG_UINT32				ui32LocalMemSize;
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+	IMG_UINT32				ui32ExtSysCacheRegsSize;
+	IMG_DEV_PHYADDR			sExtSysCacheRegsDevPBase;
+#endif
+
+
+	IMG_UINT32				ui32IRQ;
+
+#if !defined(SGX_DYNAMIC_TIMING_INFO)
+
+	SGX_TIMING_INFORMATION	sTimingInfo;
+#endif
+} SGX_DEVICE_MAP;
+
+
+struct _PVRSRV_STUB_PBDESC_
+{
+	IMG_UINT32		ui32RefCount;
+	IMG_UINT32		ui32TotalPBSize;
+	PVRSRV_KERNEL_MEM_INFO  *psSharedPBDescKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO  *psHWPBDescKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO	**ppsSubKernelMemInfos;
+	IMG_UINT32		ui32SubKernelMemInfosCount;
+	IMG_HANDLE		hDevCookie;
+	PVRSRV_KERNEL_MEM_INFO  *psBlockKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO  *psHWBlockKernelMemInfo;
+	PVRSRV_STUB_PBDESC	*psNext;
+	PVRSRV_STUB_PBDESC	**ppsThis;
+};
+
+typedef struct _PVRSRV_SGX_CCB_INFO_
+{
+	PVRSRV_KERNEL_MEM_INFO	*psCCBMemInfo;
+	PVRSRV_KERNEL_MEM_INFO	*psCCBCtlMemInfo;
+	SGXMKIF_COMMAND		*psCommands;
+	IMG_UINT32				*pui32WriteOffset;
+	volatile IMG_UINT32		*pui32ReadOffset;
+#if defined(PDUMP)
+	IMG_UINT32				ui32CCBDumpWOff;
+#endif
+} PVRSRV_SGX_CCB_INFO;
+
+PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_VOID SGXOSTimer(IMG_VOID *pvData);
+
+IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO	*psDevInfo,
+				  IMG_UINT32			 ui32PDUMPFlags);
+
+PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO	*psDevInfo);
+PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie);
+
+PVRSRV_ERROR SGXPrePowerState(IMG_HANDLE				hDevHandle,
+							  PVRSRV_DEV_POWER_STATE	eNewPowerState,
+							  PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+
+PVRSRV_ERROR SGXPostPowerState(IMG_HANDLE				hDevHandle,
+							   PVRSRV_DEV_POWER_STATE	eNewPowerState,
+							   PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+
+PVRSRV_ERROR SGXPreClockSpeedChange(IMG_HANDLE				hDevHandle,
+									IMG_BOOL				bIdleDevice,
+									PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+
+PVRSRV_ERROR SGXPostClockSpeedChange(IMG_HANDLE				hDevHandle,
+									 IMG_BOOL				bIdleDevice,
+									 PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+
+IMG_VOID SGXPanic(PVRSRV_DEVICE_NODE	*psDeviceNode);
+
+PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION *psSGXTimingInfo);
+#endif
+
+#if defined(NO_HARDWARE)
+static INLINE IMG_VOID NoHardwareGenerateEvent(PVRSRV_SGXDEV_INFO		*psDevInfo,
+												IMG_UINT32 ui32StatusRegister,
+												IMG_UINT32 ui32StatusValue,
+												IMG_UINT32 ui32StatusMask)
+{
+	IMG_UINT32 ui32RegVal;
+
+	ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32StatusRegister);
+
+	ui32RegVal &= ~ui32StatusMask;
+	ui32RegVal |= (ui32StatusValue & ui32StatusMask);
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32StatusRegister, ui32RegVal);
+}
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxinit.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxinit.c
new file mode 100644
index 0000000..45c16dc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxinit.c
@@ -0,0 +1,2267 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgx_mkif_km.h"
+#include "sgxconfig.h"
+#include "sysconfig.h"
+#include "pvr_bridge_km.h"
+
+#include "sgx_bridge_km.h"
+
+#include "pdump_km.h"
+#include "ra.h"
+#include "mmu.h"
+#include "handle.h"
+#include "perproc.h"
+
+#include "sgxutils.h"
+#include "pvrversion.h"
+#include "sgx_options.h"
+
+#include "lists.h"
+#include "srvkm.h"
+
+DECLARE_LIST_ANY_VA(PVRSRV_POWER_DEV);
+
+#if defined(SUPPORT_SGX_HWPERF)
+IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va);
+#endif
+
+#define VAR(x) #x
+
+#define CHECK_SIZE(NAME) \
+{	\
+	if (psSGXStructSizes->ui32Sizeof_##NAME != psDevInfo->sSGXStructSizes.ui32Sizeof_##NAME) \
+	{	\
+		PVR_DPF((PVR_DBG_ERROR, "SGXDevInitCompatCheck: Size check failed for SGXMKIF_%s (client) = %d bytes, (ukernel) = %d bytes\n", \
+			VAR(NAME), \
+			psDevInfo->sSGXStructSizes.ui32Sizeof_##NAME, \
+			psSGXStructSizes->ui32Sizeof_##NAME )); \
+		bStructSizesFailed = IMG_TRUE; \
+	}	\
+}
+
+#if defined (SYS_USING_INTERRUPTS)
+IMG_BOOL SGX_ISRHandler(IMG_VOID *pvData);
+#endif
+
+IMG_UINT32 gui32EventStatusServicesByISR = 0;
+
+
+static
+PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO	*psDevInfo,
+								   PVRSRV_DEVICE_NODE 	*psDeviceNode);
+
+
+static IMG_VOID SGXCommandComplete(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+#if defined(OS_SUPPORTS_IN_LISR)
+	if (OSInLISR(psDeviceNode->psSysData))
+	{
+
+		psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+	}
+	else
+	{
+		SGXScheduleProcessQueuesKM(psDeviceNode);
+	}
+#else
+	SGXScheduleProcessQueuesKM(psDeviceNode);
+#endif
+}
+
+static IMG_UINT32 DeinitDevInfo(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+	if (psDevInfo->psKernelCCBInfo != IMG_NULL)
+	{
+
+
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_SGX_CCB_INFO), psDevInfo->psKernelCCBInfo, IMG_NULL);
+	}
+
+	return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR InitDevInfo(PVRSRV_PER_PROCESS_DATA *psPerProc,
+								PVRSRV_DEVICE_NODE *psDeviceNode,
+								SGX_BRIDGE_INIT_INFO *psInitInfo)
+{
+	PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+	PVRSRV_ERROR		eError;
+
+	PVRSRV_SGX_CCB_INFO	*psKernelCCBInfo = IMG_NULL;
+
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+	psDevInfo->sScripts = psInitInfo->sScripts;
+
+	psDevInfo->psKernelCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBMemInfo;
+	psDevInfo->psKernelCCB = (PVRSRV_SGX_KERNEL_CCB *) psDevInfo->psKernelCCBMemInfo->pvLinAddrKM;
+
+	psDevInfo->psKernelCCBCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBCtlMemInfo;
+	psDevInfo->psKernelCCBCtl = (PVRSRV_SGX_CCB_CTL *) psDevInfo->psKernelCCBCtlMemInfo->pvLinAddrKM;
+
+	psDevInfo->psKernelCCBEventKickerMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBEventKickerMemInfo;
+	psDevInfo->pui32KernelCCBEventKicker = (IMG_UINT32 *)psDevInfo->psKernelCCBEventKickerMemInfo->pvLinAddrKM;
+
+	psDevInfo->psKernelSGXHostCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXHostCtlMemInfo;
+	psDevInfo->psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
+
+	psDevInfo->psKernelSGXTA3DCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXTA3DCtlMemInfo;
+
+	psDevInfo->psKernelSGXMiscMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXMiscMemInfo;
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+	psDevInfo->psKernelHWProfilingMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWProfilingMemInfo;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+	psDevInfo->psKernelHWPerfCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWPerfCBMemInfo;
+#endif
+#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
+	psDevInfo->psKernelEDMStatusBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelEDMStatusBufferMemInfo;
+#endif
+#if defined(SGX_FEATURE_OVERLAPPED_SPM)
+	psDevInfo->psKernelTmpRgnHeaderMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelTmpRgnHeaderMemInfo;
+#endif
+#if defined(SGX_FEATURE_SPM_MODE_0)
+	psDevInfo->psKernelTmpDPMStateMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelTmpDPMStateMemInfo;
+#endif
+
+	psDevInfo->ui32ClientBuildOptions = psInitInfo->ui32ClientBuildOptions;
+
+
+	psDevInfo->sSGXStructSizes = psInitInfo->sSGXStructSizes;
+
+
+
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof(PVRSRV_SGX_CCB_INFO),
+						(IMG_VOID **)&psKernelCCBInfo, 0,
+						"SGX Circular Command Buffer Info");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"InitDevInfo: Failed to alloc memory"));
+		goto failed_allockernelccb;
+	}
+
+
+	OSMemSet(psKernelCCBInfo, 0, sizeof(PVRSRV_SGX_CCB_INFO));
+	psKernelCCBInfo->psCCBMemInfo		= psDevInfo->psKernelCCBMemInfo;
+	psKernelCCBInfo->psCCBCtlMemInfo	= psDevInfo->psKernelCCBCtlMemInfo;
+	psKernelCCBInfo->psCommands			= psDevInfo->psKernelCCB->asCommands;
+	psKernelCCBInfo->pui32WriteOffset	= &psDevInfo->psKernelCCBCtl->ui32WriteOffset;
+	psKernelCCBInfo->pui32ReadOffset	= &psDevInfo->psKernelCCBCtl->ui32ReadOffset;
+	psDevInfo->psKernelCCBInfo = psKernelCCBInfo;
+
+
+
+	OSMemCopy(psDevInfo->aui32HostKickAddr, psInitInfo->aui32HostKickAddr,
+			  SGXMKIF_CMD_MAX * sizeof(psDevInfo->aui32HostKickAddr[0]));
+
+	psDevInfo->bForcePTOff = IMG_FALSE;
+
+	psDevInfo->ui32CacheControl = psInitInfo->ui32CacheControl;
+
+	psDevInfo->ui32EDMTaskReg0 = psInitInfo->ui32EDMTaskReg0;
+	psDevInfo->ui32EDMTaskReg1 = psInitInfo->ui32EDMTaskReg1;
+	psDevInfo->ui32ClkGateStatusReg = psInitInfo->ui32ClkGateStatusReg;
+	psDevInfo->ui32ClkGateStatusMask = psInitInfo->ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+	psDevInfo->ui32MasterClkGateStatusReg = psInitInfo->ui32MasterClkGateStatusReg;
+	psDevInfo->ui32MasterClkGateStatusMask = psInitInfo->ui32MasterClkGateStatusMask;
+#endif
+
+
+
+	OSMemCopy(&psDevInfo->asSGXDevData,  &psInitInfo->asInitDevData, sizeof(psDevInfo->asSGXDevData));
+
+	return PVRSRV_OK;
+
+failed_allockernelccb:
+	DeinitDevInfo(psDevInfo);
+
+	return eError;
+}
+
+
+
+
+static PVRSRV_ERROR SGXRunScript(PVRSRV_SGXDEV_INFO *psDevInfo, SGX_INIT_COMMAND *psScript, IMG_UINT32 ui32NumInitCommands)
+{
+	IMG_UINT32 ui32PC;
+	SGX_INIT_COMMAND *psComm;
+
+	for (ui32PC = 0, psComm = psScript;
+		ui32PC < ui32NumInitCommands;
+		ui32PC++, psComm++)
+	{
+		switch (psComm->eOp)
+		{
+			case SGX_INIT_OP_WRITE_HW_REG:
+			{
+				OSWriteHWReg(psDevInfo->pvRegsBaseKM, psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value);
+				PDUMPREG(psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value);
+				break;
+			}
+#if defined(PDUMP)
+			case SGX_INIT_OP_PDUMP_HW_REG:
+			{
+				PDUMPREG(psComm->sPDumpHWReg.ui32Offset, psComm->sPDumpHWReg.ui32Value);
+				break;
+			}
+#endif
+			case SGX_INIT_OP_HALT:
+			{
+				return PVRSRV_OK;
+			}
+			case SGX_INIT_OP_ILLEGAL:
+
+			default:
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SGXRunScript: PC %d: Illegal command: %d", ui32PC, psComm->eOp));
+				return PVRSRV_ERROR_GENERIC;
+			}
+		}
+
+	}
+
+	return PVRSRV_ERROR_GENERIC;
+}
+
+PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO	*psDevInfo)
+{
+	PVRSRV_ERROR			eError;
+	PVRSRV_KERNEL_MEM_INFO	*psSGXHostCtlMemInfo = psDevInfo->psKernelSGXHostCtlMemInfo;
+	SGXMKIF_HOST_CTL		*psSGXHostCtl = psSGXHostCtlMemInfo->pvLinAddrKM;
+#if defined(PDUMP)
+	static IMG_BOOL			bFirstTime = IMG_TRUE;
+#endif
+
+
+
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 1\n");
+	eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart1, SGX_MAX_INIT_COMMANDS);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXInitialise: SGXRunScript (part 1) failed (%d)", eError));
+		return (PVRSRV_ERROR_GENERIC);
+	}
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 1\n");
+
+
+	SGXReset(psDevInfo, PDUMP_FLAGS_CONTINUOUS);
+
+#if defined(EUR_CR_POWER)
+#if defined(SGX531)
+
+
+
+
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 1);
+	PDUMPREG(EUR_CR_POWER, 1);
+#else
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 0);
+	PDUMPREG(EUR_CR_POWER, 0);
+#endif
+#endif
+
+
+	*psDevInfo->pui32KernelCCBEventKicker = 0;
+#if defined(PDUMP)
+	if (bFirstTime)
+	{
+		psDevInfo->ui32KernelCCBEventKickerDumpVal = 0;
+		PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+				 psDevInfo->psKernelCCBEventKickerMemInfo, 0,
+				 sizeof(*psDevInfo->pui32KernelCCBEventKicker), PDUMP_FLAGS_CONTINUOUS,
+				 MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+	}
+#endif
+
+
+
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 2\n");
+	eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart2, SGX_MAX_INIT_COMMANDS);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXInitialise: SGXRunScript (part 2) failed (%d)", eError));
+		return (PVRSRV_ERROR_GENERIC);
+	}
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 2\n");
+
+
+	psSGXHostCtl->ui32InitStatus = 0;
+#if defined(PDUMP)
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+						  "Reset the SGX microkernel initialisation status\n");
+	PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo,
+			 offsetof(SGXMKIF_HOST_CTL, ui32InitStatus),
+			 sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+			 MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+#endif
+
+#if defined(SGX_FEATURE_MULTI_EVENT_KICK)
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+				 SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0),
+				 EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+	*psDevInfo->pui32KernelCCBEventKicker = (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+				 SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
+				 EUR_CR_EVENT_KICK_NOW_MASK);
+#endif
+
+#if defined(PDUMP)
+
+
+
+
+
+
+	if (bFirstTime)
+	{
+#if defined(SGX_FEATURE_MULTI_EVENT_KICK)
+		PDUMPREG(SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0), EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+		psDevInfo->ui32KernelCCBEventKickerDumpVal = 1;
+		PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+							  "First increment of the SGX event kicker value\n");
+		PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+				 psDevInfo->psKernelCCBEventKickerMemInfo,
+				 0,
+				 sizeof(IMG_UINT32),
+				 PDUMP_FLAGS_CONTINUOUS,
+				 MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+		PDUMPREG(SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), EUR_CR_EVENT_KICK_NOW_MASK);
+#endif
+		bFirstTime = IMG_FALSE;
+	}
+#endif
+
+#if !defined(NO_HARDWARE)
+
+
+	if (PollForValueKM(&psSGXHostCtl->ui32InitStatus,
+					   PVRSRV_USSE_EDM_INIT_COMPLETE,
+					   PVRSRV_USSE_EDM_INIT_COMPLETE,
+					   MAX_HW_TIME_US/WAIT_TRY_COUNT,
+					   WAIT_TRY_COUNT) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXInitialise: Wait for uKernel initialisation failed"));
+		PVR_DBG_BREAK;
+		return PVRSRV_ERROR_RETRY;
+	}
+#endif
+
+#if defined(PDUMP)
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+						  "Wait for the SGX microkernel initialisation to complete");
+	PDUMPMEMPOL(psSGXHostCtlMemInfo,
+				offsetof(SGXMKIF_HOST_CTL, ui32InitStatus),
+				PVRSRV_USSE_EDM_INIT_COMPLETE,
+				PVRSRV_USSE_EDM_INIT_COMPLETE,
+				PDUMP_POLL_OPERATOR_EQUAL,
+				PDUMP_FLAGS_CONTINUOUS,
+				MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+#endif
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+
+
+
+	WorkaroundBRN22997ReadHostPort(psDevInfo);
+#endif
+
+	PVR_ASSERT(psDevInfo->psKernelCCBCtl->ui32ReadOffset == psDevInfo->psKernelCCBCtl->ui32WriteOffset);
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie)
+
+{
+	PVRSRV_SGXDEV_INFO	*psDevInfo = (PVRSRV_SGXDEV_INFO *) hDevCookie;
+	PVRSRV_ERROR		eError;
+
+
+	if (psDevInfo->pvRegsBaseKM == IMG_NULL)
+	{
+		return PVRSRV_OK;
+	}
+
+	eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asDeinitCommands, SGX_MAX_DEINIT_COMMANDS);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXDeinitialise: SGXRunScript failed (%d)", eError));
+		return (PVRSRV_ERROR_GENERIC);
+	}
+
+	return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode)
+{
+	PVRSRV_SGXDEV_INFO	*psDevInfo;
+	IMG_HANDLE		hKernelDevMemContext;
+	IMG_DEV_PHYADDR		sPDDevPAddr;
+	IMG_UINT32		i;
+	PVRSRV_DEVICE_NODE  *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+	DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+	PVRSRV_ERROR		eError;
+
+	PDUMPCOMMENT("SGX Initialisation Part 1");
+
+
+	PDUMPCOMMENT("SGX Core Version Information: %s", SGX_CORE_FRIENDLY_NAME);
+#ifdef SGX_CORE_REV
+	PDUMPCOMMENT("SGX Core Revision Information: %d", SGX_CORE_REV);
+#else
+	PDUMPCOMMENT("SGX Core Revision Information: head rtl");
+#endif
+
+	#if defined(SGX_FEATURE_SYSTEM_CACHE)
+	PDUMPCOMMENT("SGX System Level Cache is present\r\n");
+	#if defined(SGX_BYPASS_SYSTEM_CACHE)
+	PDUMPCOMMENT("SGX System Level Cache is bypassed\r\n");
+	#endif
+	#endif
+
+
+	if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_SGXDEV_INFO),
+					 (IMG_VOID **)&psDevInfo, IMG_NULL,
+					 "SGX Device Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart1 : Failed to alloc memory for DevInfo"));
+		return (PVRSRV_ERROR_OUT_OF_MEMORY);
+	}
+	OSMemSet (psDevInfo, 0, sizeof(PVRSRV_SGXDEV_INFO));
+
+
+	psDevInfo->eDeviceType 		= DEV_DEVICE_TYPE;
+	psDevInfo->eDeviceClass 	= DEV_DEVICE_CLASS;
+
+
+	psDeviceNode->pvDevice = (IMG_PVOID)psDevInfo;
+
+
+	psDevInfo->pvDeviceMemoryHeap = (IMG_VOID*)psDeviceMemoryHeap;
+
+
+	hKernelDevMemContext = BM_CreateContext(psDeviceNode,
+											&sPDDevPAddr,
+											IMG_NULL,
+											IMG_NULL);
+	if (hKernelDevMemContext == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart1: Failed BM_CreateContext"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	psDevInfo->sKernelPDDevPAddr = sPDDevPAddr;
+
+
+	for(i=0; i<psDeviceNode->sDevMemoryInfo.ui32HeapCount; i++)
+	{
+		IMG_HANDLE hDevMemHeap;
+
+		switch(psDeviceMemoryHeap[i].DevMemHeapType)
+		{
+			case DEVICE_MEMORY_HEAP_KERNEL:
+			case DEVICE_MEMORY_HEAP_SHARED:
+			case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+			{
+				hDevMemHeap = BM_CreateHeap (hKernelDevMemContext,
+												&psDeviceMemoryHeap[i]);
+
+
+
+				psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap;
+				break;
+			}
+		}
+	}
+
+	eError = MMU_BIFResetPDAlloc(psDevInfo);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevInitSGX : Failed to alloc memory for BIF reset"));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle, SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo)
+{
+	PVRSRV_DEVICE_NODE	*psDeviceNode;
+	PVRSRV_SGXDEV_INFO	*psDevInfo;
+	PVRSRV_ERROR		eError;
+
+	PDUMPCOMMENT("SGXGetInfoForSrvinit");
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
+	psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+	psInitInfo->sPDDevPAddr = psDevInfo->sKernelPDDevPAddr;
+
+	eError = PVRSRVGetDeviceMemHeapsKM(hDevHandle, &psInitInfo->asHeapInfo[0]);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXGetInfoForSrvinit: PVRSRVGetDeviceMemHeapsKM failed (%d)", eError));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR DevInitSGXPart2KM (PVRSRV_PER_PROCESS_DATA *psPerProc,
+                                IMG_HANDLE hDevHandle,
+                                SGX_BRIDGE_INIT_INFO *psInitInfo)
+{
+	PVRSRV_DEVICE_NODE		*psDeviceNode;
+	PVRSRV_SGXDEV_INFO		*psDevInfo;
+	PVRSRV_ERROR			eError;
+	SGX_DEVICE_MAP			*psSGXDeviceMap;
+	PVRSRV_DEV_POWER_STATE	eDefaultPowerState;
+
+	PDUMPCOMMENT("SGX Initialisation Part 2");
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
+	psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+
+
+	eError = InitDevInfo(psPerProc, psDeviceNode, psInitInfo);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to load EDM program"));
+		goto failed_init_dev_info;
+	}
+
+
+	eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+									(IMG_VOID**)&psSGXDeviceMap);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to get device memory map!"));
+		return PVRSRV_ERROR_INIT_FAILURE;
+	}
+
+
+	if (psSGXDeviceMap->pvRegsCpuVBase)
+	{
+		psDevInfo->pvRegsBaseKM = psSGXDeviceMap->pvRegsCpuVBase;
+	}
+	else
+	{
+
+		psDevInfo->pvRegsBaseKM = OSMapPhysToLin(psSGXDeviceMap->sRegsCpuPBase,
+											   psSGXDeviceMap->ui32RegsSize,
+											   PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+											   IMG_NULL);
+		if (!psDevInfo->pvRegsBaseKM)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to map in regs\n"));
+			return PVRSRV_ERROR_BAD_MAPPING;
+		}
+	}
+	psDevInfo->ui32RegSize = psSGXDeviceMap->ui32RegsSize;
+	psDevInfo->sRegsPhysBase = psSGXDeviceMap->sRegsSysPBase;
+
+
+#if defined(SGX_FEATURE_HOST_PORT)
+	if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT)
+	{
+
+		psDevInfo->pvHostPortBaseKM = OSMapPhysToLin(psSGXDeviceMap->sHPCpuPBase,
+									  	           psSGXDeviceMap->ui32HPSize,
+									  	           PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+									  	           IMG_NULL);
+		if (!psDevInfo->pvHostPortBaseKM)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to map in host port\n"));
+			return PVRSRV_ERROR_BAD_MAPPING;
+		}
+		psDevInfo->ui32HPSize = psSGXDeviceMap->ui32HPSize;
+		psDevInfo->sHPSysPAddr = psSGXDeviceMap->sHPSysPBase;
+	}
+#endif
+
+#if defined (SYS_USING_INTERRUPTS)
+
+
+	psDeviceNode->pvISRData = psDeviceNode;
+
+	PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler);
+
+#endif
+
+
+	psDevInfo->psSGXHostCtl->ui32PowerStatus |= PVRSRV_USSE_EDM_POWMAN_NO_WORK;
+	eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
+
+	eError = PVRSRVRegisterPowerDevice (psDeviceNode->sDevId.ui32DeviceIndex,
+										SGXPrePowerState, SGXPostPowerState,
+										SGXPreClockSpeedChange, SGXPostClockSpeedChange,
+										(IMG_HANDLE)psDeviceNode,
+										PVRSRV_DEV_POWER_STATE_OFF,
+										eDefaultPowerState);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: failed to register device with power manager"));
+		return eError;
+	}
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+	eError = WorkaroundBRN22997Alloc(psDevInfo);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to alloc memory for BRN22997 workaround"));
+		return eError;
+	}
+#endif
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+
+	psDevInfo->ui32ExtSysCacheRegsSize = psSGXDeviceMap->ui32ExtSysCacheRegsSize;
+	psDevInfo->sExtSysCacheRegsDevPBase = psSGXDeviceMap->sExtSysCacheRegsDevPBase;
+	eError = MMU_MapExtSystemCacheRegs(psDeviceNode);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to map external system cache registers"));
+		return eError;
+	}
+#endif
+
+
+
+	OSMemSet(psDevInfo->psKernelCCB, 0, sizeof(PVRSRV_SGX_KERNEL_CCB));
+	OSMemSet(psDevInfo->psKernelCCBCtl, 0, sizeof(PVRSRV_SGX_CCB_CTL));
+	OSMemSet(psDevInfo->pui32KernelCCBEventKicker, 0, sizeof(*psDevInfo->pui32KernelCCBEventKicker));
+	PDUMPCOMMENT("Initialise Kernel CCB");
+	PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBMemInfo, 0, sizeof(PVRSRV_SGX_KERNEL_CCB), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBMemInfo));
+	PDUMPCOMMENT("Initialise Kernel CCB Control");
+	PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBCtlMemInfo, 0, sizeof(PVRSRV_SGX_CCB_CTL), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBCtlMemInfo));
+	PDUMPCOMMENT("Initialise Kernel CCB Event Kicker");
+	PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0, sizeof(*psDevInfo->pui32KernelCCBEventKicker), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+
+	return PVRSRV_OK;
+
+failed_init_dev_info:
+	return eError;
+}
+
+static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
+{
+	PVRSRV_DEVICE_NODE			*psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+	PVRSRV_SGXDEV_INFO			*psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+	PVRSRV_ERROR				eError;
+	IMG_UINT32					ui32Heap;
+	DEVICE_MEMORY_HEAP_INFO		*psDeviceMemoryHeap;
+	SGX_DEVICE_MAP				*psSGXDeviceMap;
+
+	if (!psDevInfo)
+	{
+
+		PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Null DevInfo"));
+		return PVRSRV_OK;
+	}
+
+#if defined(SUPPORT_HW_RECOVERY)
+	if (psDevInfo->hTimer)
+	{
+		eError = OSRemoveTimer(psDevInfo->hTimer);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to remove timer"));
+			return 	eError;
+		}
+		psDevInfo->hTimer = IMG_NULL;
+	}
+#endif
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+
+	eError = MMU_UnmapExtSystemCacheRegs(psDeviceNode);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to unmap ext system cache registers"));
+		return eError;
+	}
+#endif
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+	WorkaroundBRN22997Free(psDevInfo);
+#endif
+
+	MMU_BIFResetPDFree(psDevInfo);
+
+
+
+
+	DeinitDevInfo(psDevInfo);
+
+
+	psDeviceMemoryHeap = (DEVICE_MEMORY_HEAP_INFO *)psDevInfo->pvDeviceMemoryHeap;
+	for(ui32Heap=0; ui32Heap<psDeviceNode->sDevMemoryInfo.ui32HeapCount; ui32Heap++)
+	{
+		switch(psDeviceMemoryHeap[ui32Heap].DevMemHeapType)
+		{
+			case DEVICE_MEMORY_HEAP_KERNEL:
+			case DEVICE_MEMORY_HEAP_SHARED:
+			case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+			{
+				if (psDeviceMemoryHeap[ui32Heap].hDevMemHeap != IMG_NULL)
+				{
+					BM_DestroyHeap(psDeviceMemoryHeap[ui32Heap].hDevMemHeap);
+				}
+				break;
+			}
+		}
+	}
+
+
+	eError = BM_DestroyContext(psDeviceNode->sDevMemoryInfo.pBMKernelContext, IMG_NULL);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX : Failed to destroy kernel context"));
+		return eError;
+	}
+
+
+	eError = PVRSRVRemovePowerDevice (((PVRSRV_DEVICE_NODE*)pvDeviceNode)->sDevId.ui32DeviceIndex);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+									(IMG_VOID**)&psSGXDeviceMap);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to get device memory map!"));
+		return eError;
+	}
+
+
+	if (!psSGXDeviceMap->pvRegsCpuVBase)
+	{
+
+		if (psDevInfo->pvRegsBaseKM != IMG_NULL)
+		{
+			OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
+							 psDevInfo->ui32RegSize,
+							 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+							 IMG_NULL);
+		}
+	}
+
+#if defined(SGX_FEATURE_HOST_PORT)
+	if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT)
+	{
+
+		if (psDevInfo->pvHostPortBaseKM != IMG_NULL)
+		{
+			OSUnMapPhysToLin(psDevInfo->pvHostPortBaseKM,
+						   psDevInfo->ui32HPSize,
+						   PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+						   IMG_NULL);
+		}
+	}
+#endif
+
+
+
+	OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				sizeof(PVRSRV_SGXDEV_INFO),
+				psDevInfo,
+				0);
+
+	psDeviceNode->pvDevice = IMG_NULL;
+
+	if (psDeviceMemoryHeap != IMG_NULL)
+	{
+
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID,
+				psDeviceMemoryHeap,
+				0);
+	}
+
+	return PVRSRV_OK;
+}
+
+
+IMG_VOID SGXDumpDebugInfo (PVRSRV_DEVICE_NODE *psDeviceNode,
+						   IMG_BOOL			  bDumpSGXRegs)
+{
+	IMG_UINT			ui32RegVal;
+	PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+
+	if (bDumpSGXRegs)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGX Register Base Address (Linear):   0x%08X", psDevInfo->pvRegsBaseKM));
+		PVR_DPF((PVR_DBG_ERROR,"SGX Register Base Address (Physical): 0x%08X", psDevInfo->sRegsPhysBase));
+
+
+
+
+		ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
+		if (ui32RegVal & (EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK | EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK))
+		{
+			PVR_LOG(("DPM out of memory!!"));
+		}
+		PVR_LOG(("EUR_CR_EVENT_STATUS:     %x", ui32RegVal));
+
+		ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
+		PVR_LOG(("EUR_CR_EVENT_STATUS2:    %x", ui32RegVal));
+
+		ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL);
+		PVR_LOG(("EUR_CR_BIF_CTRL:         %x", ui32RegVal));
+
+		#if defined(EUR_CR_BIF_BANK0)
+		ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0);
+		PVR_LOG(("EUR_CR_BIF_BANK0:        %x", ui32RegVal));
+		#endif
+
+		ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+		PVR_LOG(("EUR_CR_BIF_INT_STAT:     %x", ui32RegVal));
+
+		ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT);
+		PVR_LOG(("EUR_CR_BIF_FAULT:        %x", ui32RegVal));
+
+		ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_MEM_REQ_STAT);
+		PVR_LOG(("EUR_CR_BIF_MEM_REQ_STAT: %x", ui32RegVal));
+
+		ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_CLKGATECTL);
+		PVR_LOG(("EUR_CR_CLKGATECTL:       %x", ui32RegVal));
+
+		#if defined(EUR_CR_PDS_PC_BASE)
+		ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_PDS_PC_BASE);
+		PVR_LOG(("EUR_CR_PDS_PC_BASE:      %x", ui32RegVal));
+		#endif
+
+
+	}
+
+	#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+	{
+		IMG_UINT32	*pui32MKTraceBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM;
+		IMG_UINT32	ui32LastStatusCode, ui32WriteOffset;
+
+		ui32LastStatusCode = *pui32MKTraceBuffer;
+		pui32MKTraceBuffer++;
+		ui32WriteOffset = *pui32MKTraceBuffer;
+		pui32MKTraceBuffer++;
+
+		PVR_LOG(("Last SGX microkernel status code: 0x%x", ui32LastStatusCode));
+
+		#if defined(PVRSRV_DUMP_MK_TRACE)
+
+
+		{
+			IMG_UINT32	ui32LoopCounter;
+
+			for (ui32LoopCounter = 0;
+				 ui32LoopCounter < SGXMK_TRACE_BUFFER_SIZE;
+				 ui32LoopCounter++)
+			{
+				IMG_UINT32	*pui32BufPtr;
+				pui32BufPtr = pui32MKTraceBuffer +
+								(((ui32WriteOffset + ui32LoopCounter) % SGXMK_TRACE_BUFFER_SIZE) * 4);
+				PVR_LOG(("(MKT%u) %08X %08X %08X %08X", ui32LoopCounter,
+						 pui32BufPtr[2], pui32BufPtr[3], pui32BufPtr[1], pui32BufPtr[0]));
+			}
+		}
+		#endif
+	}
+	#endif
+
+	{
+
+
+		IMG_UINT32	*pui32HostCtlBuffer = (IMG_UINT32 *)psDevInfo->psSGXHostCtl;
+		IMG_UINT32	ui32LoopCounter;
+
+		PVR_LOG(("SGX Host control:"));
+
+		for (ui32LoopCounter = 0;
+			 ui32LoopCounter < sizeof(*psDevInfo->psSGXHostCtl) / sizeof(*pui32HostCtlBuffer);
+			 ui32LoopCounter += 4)
+		{
+			PVR_LOG(("\t0x%X: 0x%08X 0x%08X 0x%08X 0x%08X", ui32LoopCounter * sizeof(*pui32HostCtlBuffer),
+					pui32HostCtlBuffer[ui32LoopCounter + 0], pui32HostCtlBuffer[ui32LoopCounter + 1],
+					pui32HostCtlBuffer[ui32LoopCounter + 2], pui32HostCtlBuffer[ui32LoopCounter + 3]));
+		}
+	}
+
+	{
+
+
+		IMG_UINT32	*pui32TA3DCtlBuffer = psDevInfo->psKernelSGXTA3DCtlMemInfo->pvLinAddrKM;
+		IMG_UINT32	ui32LoopCounter;
+
+		PVR_LOG(("SGX TA/3D control:"));
+
+		for (ui32LoopCounter = 0;
+			 ui32LoopCounter < psDevInfo->psKernelSGXTA3DCtlMemInfo->ui32AllocSize / sizeof(*pui32TA3DCtlBuffer);
+			 ui32LoopCounter += 4)
+		{
+			PVR_LOG(("\t0x%X: 0x%08X 0x%08X 0x%08X 0x%08X", ui32LoopCounter * sizeof(*pui32TA3DCtlBuffer),
+					pui32TA3DCtlBuffer[ui32LoopCounter + 0], pui32TA3DCtlBuffer[ui32LoopCounter + 1],
+					pui32TA3DCtlBuffer[ui32LoopCounter + 2], pui32TA3DCtlBuffer[ui32LoopCounter + 3]));
+		}
+	}
+
+	QueueDumpDebugInfo();
+}
+
+
+#if defined(SYS_USING_INTERRUPTS) || defined(SUPPORT_HW_RECOVERY)
+static
+IMG_VOID HWRecoveryResetSGX (PVRSRV_DEVICE_NODE *psDeviceNode,
+							 IMG_UINT32 		ui32Component,
+							 IMG_UINT32			ui32CallerID)
+{
+	PVRSRV_ERROR		eError;
+	PVRSRV_SGXDEV_INFO	*psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+	SGXMKIF_HOST_CTL	*psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Component);
+
+
+
+	eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+	if(eError != PVRSRV_OK)
+	{
+
+
+
+		PVR_DPF((PVR_DBG_WARNING,"HWRecoveryResetSGX: Power transition in progress"));
+		return;
+	}
+
+	psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
+
+	PVR_LOG(("HWRecoveryResetSGX: SGX Hardware Recovery triggered"));
+
+	SGXDumpDebugInfo(psDeviceNode, IMG_TRUE);
+
+
+	PDUMPSUSPEND();
+
+
+	eError = SGXInitialise(psDevInfo);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"HWRecoveryResetSGX: SGXInitialise failed (%d)", eError));
+	}
+
+
+	PDUMPRESUME();
+
+	PVRSRVPowerUnlock(ui32CallerID);
+
+
+	SGXScheduleProcessQueuesKM(psDeviceNode);
+
+
+
+	PVRSRVProcessQueues(ui32CallerID, IMG_TRUE);
+}
+#endif
+
+
+#if defined(SUPPORT_HW_RECOVERY)
+IMG_VOID SGXOSTimer(IMG_VOID *pvData)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode = pvData;
+	PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+	static IMG_UINT32	ui32EDMTasks = 0;
+	static IMG_UINT32	ui32LockupCounter = 0;
+	static IMG_UINT32	ui32NumResets = 0;
+	IMG_UINT32		ui32CurrentEDMTasks;
+	IMG_BOOL		bLockup = IMG_FALSE;
+	IMG_BOOL		bPoweredDown;
+
+
+	psDevInfo->ui32TimeStamp++;
+
+#if defined(NO_HARDWARE)
+	bPoweredDown = IMG_TRUE;
+#else
+	bPoweredDown = SGXIsDevicePowered(psDeviceNode) ? IMG_FALSE : IMG_TRUE;
+#endif
+
+
+
+	if (bPoweredDown)
+	{
+		ui32LockupCounter = 0;
+	}
+	else
+	{
+
+		ui32CurrentEDMTasks = OSReadHWReg(psDevInfo->pvRegsBaseKM, psDevInfo->ui32EDMTaskReg0);
+		if (psDevInfo->ui32EDMTaskReg1 != 0)
+		{
+			ui32CurrentEDMTasks ^= OSReadHWReg(psDevInfo->pvRegsBaseKM, psDevInfo->ui32EDMTaskReg1);
+		}
+		if ((ui32CurrentEDMTasks == ui32EDMTasks) &&
+			(psDevInfo->ui32NumResets == ui32NumResets))
+		{
+			ui32LockupCounter++;
+			if (ui32LockupCounter == 3)
+			{
+				ui32LockupCounter = 0;
+				PVR_DPF((PVR_DBG_ERROR, "SGXOSTimer() detected SGX lockup (0x%x tasks)", ui32EDMTasks));
+
+				bLockup = IMG_TRUE;
+			}
+		}
+		else
+		{
+			ui32LockupCounter = 0;
+			ui32EDMTasks = ui32CurrentEDMTasks;
+			ui32NumResets = psDevInfo->ui32NumResets;
+		}
+	}
+
+	if (bLockup)
+	{
+		SGXMKIF_HOST_CTL	*psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+
+		psSGXHostCtl->ui32HostDetectedLockups ++;
+
+		PVR_LOG(("HWRecoveryResetSGX: From Kernel"));
+
+		HWRecoveryResetSGX(psDeviceNode, 0, KERNEL_ID);
+	}
+}
+#endif
+
+
+#if defined(SYS_USING_INTERRUPTS)
+
+IMG_BOOL SGX_ISRHandler (IMG_VOID *pvData)
+{
+	IMG_BOOL bInterruptProcessed = IMG_FALSE;
+
+
+
+	{
+		IMG_UINT32 ui32EventStatus, ui32EventEnable;
+		IMG_UINT32 ui32EventClear = 0;
+		PVRSRV_DEVICE_NODE *psDeviceNode;
+		PVRSRV_SGXDEV_INFO *psDevInfo;
+
+
+		if(pvData == IMG_NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "SGX_ISRHandler: Invalid params\n"));
+			return bInterruptProcessed;
+		}
+
+		psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+		psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+		ui32EventStatus = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
+		ui32EventEnable = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE);
+
+
+
+		gui32EventStatusServicesByISR = ui32EventStatus;
+
+
+		ui32EventStatus &= ui32EventEnable;
+
+		if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK)
+		{
+			ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK;
+		}
+
+		if (ui32EventClear)
+		{
+			bInterruptProcessed = IMG_TRUE;
+
+
+			ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK;
+
+
+			OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32EventClear);
+		}
+	}
+
+	return bInterruptProcessed;
+}
+
+
+IMG_VOID SGX_MISRHandler (IMG_VOID *pvData)
+{
+	PVRSRV_DEVICE_NODE	*psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+	PVRSRV_SGXDEV_INFO	*psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+	SGXMKIF_HOST_CTL	*psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+	if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR) != 0UL) &&
+		((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR) == 0UL))
+	{
+		PVR_LOG(("HWRecoveryResetSGX: From ISR"));
+		HWRecoveryResetSGX(psDeviceNode, 0, ISR_ID);
+	}
+
+#if defined(OS_SUPPORTS_IN_LISR)
+	if (psDeviceNode->bReProcessDeviceCommandComplete)
+	{
+		SGXScheduleProcessQueuesKM(psDeviceNode);
+	}
+#endif
+
+	SGXTestActivePowerEvent(psDeviceNode, ISR_ID);
+}
+#endif
+
+
+PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	DEVICE_MEMORY_INFO *psDevMemoryInfo;
+	DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+
+	psDeviceNode->sDevId.eDeviceType	= DEV_DEVICE_TYPE;
+	psDeviceNode->sDevId.eDeviceClass	= DEV_DEVICE_CLASS;
+
+	psDeviceNode->pfnInitDevice		= DevInitSGXPart1;
+	psDeviceNode->pfnDeInitDevice		= DevDeInitSGX;
+
+	psDeviceNode->pfnInitDeviceCompatCheck	= SGXDevInitCompatCheck;
+
+
+
+	psDeviceNode->pfnMMUInitialise = MMU_Initialise;
+	psDeviceNode->pfnMMUFinalise = MMU_Finalise;
+	psDeviceNode->pfnMMUInsertHeap = MMU_InsertHeap;
+	psDeviceNode->pfnMMUCreate = MMU_Create;
+	psDeviceNode->pfnMMUDelete = MMU_Delete;
+	psDeviceNode->pfnMMUAlloc = MMU_Alloc;
+	psDeviceNode->pfnMMUFree = MMU_Free;
+	psDeviceNode->pfnMMUMapPages = MMU_MapPages;
+	psDeviceNode->pfnMMUMapShadow = MMU_MapShadow;
+	psDeviceNode->pfnMMUUnmapPages = MMU_UnmapPages;
+	psDeviceNode->pfnMMUMapScatter = MMU_MapScatter;
+	psDeviceNode->pfnMMUGetPhysPageAddr = MMU_GetPhysPageAddr;
+	psDeviceNode->pfnMMUGetPDDevPAddr = MMU_GetPDDevPAddr;
+
+#if defined (SYS_USING_INTERRUPTS)
+
+
+	psDeviceNode->pfnDeviceISR = SGX_ISRHandler;
+	psDeviceNode->pfnDeviceMISR = SGX_MISRHandler;
+#endif
+
+
+
+	psDeviceNode->pfnDeviceCommandComplete = SGXCommandComplete;
+
+
+
+	psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+	psDevMemoryInfo->ui32AddressSpaceSizeLog2 = SGX_FEATURE_ADDRESS_SPACE_SIZE;
+
+
+	psDevMemoryInfo->ui32Flags = 0;
+
+
+	if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID,
+					 (IMG_VOID **)&psDevMemoryInfo->psDeviceMemoryHeap, 0,
+					 "Array of Device Memory Heap Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXRegisterDevice : Failed to alloc memory for DEVICE_MEMORY_HEAP_INFO"));
+		return (PVRSRV_ERROR_OUT_OF_MEMORY);
+	}
+	OSMemSet(psDevMemoryInfo->psDeviceMemoryHeap, 0, sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID);
+
+	psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+
+
+
+
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+														| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+														| PVRSRV_HAP_SINGLE_PROCESS;
+	psDeviceMemoryHeap->pszName = "General";
+	psDeviceMemoryHeap->pszBSName = "General BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+#if !defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+
+	psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+#endif
+	psDeviceMemoryHeap++;
+
+
+
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_TADATA_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_TADATA_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+														| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+														| PVRSRV_HAP_MULTI_PROCESS;
+	psDeviceMemoryHeap->pszName = "TA Data";
+	psDeviceMemoryHeap->pszBSName = "TA Data BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;
+
+
+
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_CODE_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_CODE_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+															| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+															| PVRSRV_HAP_MULTI_PROCESS;
+	psDeviceMemoryHeap->pszName = "Kernel Code";
+	psDeviceMemoryHeap->pszBSName = "Kernel Code BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;
+
+
+
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_DATA_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_DATA_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_DATA_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+																| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+																| PVRSRV_HAP_MULTI_PROCESS;
+	psDeviceMemoryHeap->pszName = "KernelData";
+	psDeviceMemoryHeap->pszBSName = "KernelData BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;
+
+
+
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PIXELSHADER_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_PIXELSHADER_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+																| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+																| PVRSRV_HAP_SINGLE_PROCESS;
+	psDeviceMemoryHeap->pszName = "PixelShaderUSSE";
+	psDeviceMemoryHeap->pszBSName = "PixelShaderUSSE BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;
+
+
+
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VERTEXSHADER_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_VERTEXSHADER_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+																| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+																| PVRSRV_HAP_SINGLE_PROCESS;
+	psDeviceMemoryHeap->pszName = "VertexShaderUSSE";
+	psDeviceMemoryHeap->pszBSName = "VertexShaderUSSE BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;
+
+
+
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSPIXEL_CODEDATA_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_PDSPIXEL_CODEDATA_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+																| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+																| PVRSRV_HAP_SINGLE_PROCESS;
+	psDeviceMemoryHeap->pszName = "PDSPixelCodeData";
+	psDeviceMemoryHeap->pszBSName = "PDSPixelCodeData BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;
+
+
+
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSVERTEX_CODEDATA_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_PDSVERTEX_CODEDATA_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+																| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+																| PVRSRV_HAP_SINGLE_PROCESS;
+	psDeviceMemoryHeap->pszName = "PDSVertexCodeData";
+	psDeviceMemoryHeap->pszBSName = "PDSVertexCodeData BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;
+
+
+
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_SYNCINFO_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_SYNCINFO_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+														| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+														| PVRSRV_HAP_MULTI_PROCESS;
+	psDeviceMemoryHeap->pszName = "CacheCoherent";
+	psDeviceMemoryHeap->pszBSName = "CacheCoherent BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+
+	psDevMemoryInfo->ui32SyncHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+	psDeviceMemoryHeap++;
+
+
+
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_3DPARAMETERS_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_3DPARAMETERS_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_3DPARAMETERS_HEAP_SIZE;
+	psDeviceMemoryHeap->pszName = "3DParameters";
+	psDeviceMemoryHeap->pszBSName = "3DParameters BS";
+#if defined(SUPPORT_PERCONTEXT_PB)
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+															| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+															| PVRSRV_HAP_SINGLE_PROCESS;
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+#else
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+													| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+													| PVRSRV_HAP_MULTI_PROCESS;
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+#endif
+
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;
+
+
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_MAPPING_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_MAPPING_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_MAPPING_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_MULTI_PROCESS;
+	psDeviceMemoryHeap->pszName = "GeneralMapping";
+	psDeviceMemoryHeap->pszBSName = "GeneralMapping BS";
+	#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410)
+
+
+
+
+
+
+
+		psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+#else
+		psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+#endif
+
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+
+	psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+	psDeviceMemoryHeap++;
+#endif
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_2D_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_2D_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_2D_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+														| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+														| PVRSRV_HAP_SINGLE_PROCESS;
+	psDeviceMemoryHeap->pszName = "2D";
+	psDeviceMemoryHeap->pszBSName = "2D BS";
+
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;
+#endif
+
+
+#if defined(FIX_HW_BRN_26915)
+
+
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_CGBUFFER_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_CGBUFFER_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_CGBUFFER_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+														| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+														| PVRSRV_HAP_SINGLE_PROCESS;
+	psDeviceMemoryHeap->pszName = "CGBuffer";
+	psDeviceMemoryHeap->pszBSName = "CGBuffer BS";
+
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;
+#endif
+
+#if defined(SUPPORT_SGX_VIDEO_HEAP)
+
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VIDEO_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VIDEO_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_VIDEO_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+										| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+										| PVRSRV_HAP_MULTI_PROCESS;
+	psDeviceMemoryHeap->pszName = "Video";
+	psDeviceMemoryHeap->pszBSName = "Video BS";
+
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;
+#endif
+
+
+	psDevMemoryInfo->ui32HeapCount = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+
+	return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE					hDevCookie,
+								SGX_CLIENT_INFO*		psClientInfo)
+{
+	PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+
+
+	psDevInfo->ui32ClientRefCount++;
+
+#if defined(PDUMP)
+
+	psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0;
+#endif
+
+
+	psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+
+
+	OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData, sizeof(psClientInfo->asDevData));
+
+
+	return PVRSRV_OK;
+}
+
+
+IMG_VOID SGXPanic(PVRSRV_DEVICE_NODE	*psDeviceNode)
+{
+	PVR_LOG(("SGX panic"));
+	SGXDumpDebugInfo(psDeviceNode, IMG_FALSE);
+	OSPanic();
+}
+
+
+PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_ERROR	eError;
+	PVRSRV_SGXDEV_INFO 				*psDevInfo;
+	IMG_UINT32 			ui32BuildOptions, ui32BuildOptionsMismatch;
+#if !defined(NO_HARDWARE)
+	PPVRSRV_KERNEL_MEM_INFO			psMemInfo;
+	PVRSRV_SGX_MISCINFO_INFO		*psSGXMiscInfoInt;
+	PVRSRV_SGX_MISCINFO_FEATURES	*psSGXFeatures;
+	SGX_MISCINFO_STRUCT_SIZES		*psSGXStructSizes;
+	IMG_BOOL						bStructSizesFailed;
+
+
+	IMG_BOOL	bCheckCoreRev;
+	const IMG_UINT32	aui32CoreRevExceptions[] =
+		{
+			0x10100, 0x10101
+		};
+	const IMG_UINT32	ui32NumCoreExceptions = sizeof(aui32CoreRevExceptions) / (2*sizeof(IMG_UINT32));
+	IMG_UINT	i;
+#endif
+
+
+	if(psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_SGX)
+	{
+		PVR_LOG(("(FAIL) SGXInit: Device not of type SGX"));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto chk_exit;
+	}
+
+	psDevInfo = psDeviceNode->pvDevice;
+
+
+
+	ui32BuildOptions = (SGX_BUILD_OPTIONS);
+#if defined(DEBUG) || defined (INTERNAL_TEST)
+	/* Workaround: During development, the DEBUG bit can get out of sync, so
+	 * ignore that bit:
+	 */
+	if (0x1 & ui32BuildOptions) {
+		psDevInfo->ui32ClientBuildOptions =
+			psDevInfo->ui32ClientBuildOptions | 0x1;
+	} else {
+		psDevInfo->ui32ClientBuildOptions =
+			psDevInfo->ui32ClientBuildOptions & 0xfffffffe;
+	}
+#endif
+	if (ui32BuildOptions != psDevInfo->ui32ClientBuildOptions)
+	{
+		ui32BuildOptionsMismatch = ui32BuildOptions ^ psDevInfo->ui32ClientBuildOptions;
+		if ( (psDevInfo->ui32ClientBuildOptions & ui32BuildOptionsMismatch) != 0)
+		{
+			PVR_LOG(("(FAIL) SGXInit: Mismatch in client-side and KM driver build options; "
+				"extra options present in client-side driver: (0x%lx). Please check sgx_options.h",
+				psDevInfo->ui32ClientBuildOptions & ui32BuildOptionsMismatch ));
+		}
+
+		if ( (ui32BuildOptions & ui32BuildOptionsMismatch) != 0)
+		{
+			PVR_LOG(("(FAIL) SGXInit: Mismatch in client-side and KM driver build options; "
+				"extra options present in KM: (0x%lx). Please check sgx_options.h",
+				ui32BuildOptions & ui32BuildOptionsMismatch ));
+		}
+		eError = PVRSRV_ERROR_BUILD_MISMATCH;
+		goto chk_exit;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: Client-side and KM driver build options match. [ OK ]"));
+	}
+
+#if !defined (NO_HARDWARE)
+	psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
+
+	psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
+	psSGXMiscInfoInt->ui32MiscInfoFlags = 0;
+	psSGXMiscInfoInt->ui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES;
+	eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode);
+
+
+	if(eError != PVRSRV_OK)
+	{
+		PVR_LOG(("(FAIL) SGXInit: Unable to validate device DDK version"));
+		goto chk_exit;
+	}
+	psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+	if( (psSGXFeatures->ui32DDKVersion !=
+		((PVRVERSION_MAJ << 16) |
+		 (PVRVERSION_MIN << 8) |
+		  PVRVERSION_BRANCH) ) ||
+		(psSGXFeatures->ui32DDKBuild != PVRVERSION_BUILD) )
+	{
+		PVR_LOG(("(FAIL) SGXInit: Incompatible driver DDK revision (%ld)/device DDK revision (%ld).",
+				PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild));
+		eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
+		PVR_DBG_BREAK;
+		goto chk_exit;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: driver DDK (%ld) and device DDK (%ld) match. [ OK ]",
+				PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild));
+	}
+
+
+	if (psSGXFeatures->ui32CoreRevSW == 0)
+	{
+
+
+		PVR_LOG(("SGXInit: HW core rev (%lx) check skipped.",
+				psSGXFeatures->ui32CoreRev));
+	}
+	else
+	{
+
+		bCheckCoreRev = IMG_TRUE;
+		for(i=0; i<ui32NumCoreExceptions; i+=2)
+		{
+			if( (psSGXFeatures->ui32CoreRev==aui32CoreRevExceptions[i]) &&
+				(psSGXFeatures->ui32CoreRevSW==aui32CoreRevExceptions[i+1])	)
+			{
+				PVR_LOG(("SGXInit: HW core rev (%lx), SW core rev (%lx) check skipped.",
+						psSGXFeatures->ui32CoreRev,
+						psSGXFeatures->ui32CoreRevSW));
+				bCheckCoreRev = IMG_FALSE;
+			}
+		}
+
+		if (bCheckCoreRev)
+		{
+			if (psSGXFeatures->ui32CoreRev != psSGXFeatures->ui32CoreRevSW)
+			{
+				PVR_LOG(("(FAIL) SGXInit: Incompatible HW core rev (%lx) and SW core rev (%lx).",
+						psSGXFeatures->ui32CoreRev, psSGXFeatures->ui32CoreRevSW));
+						eError = PVRSRV_ERROR_BUILD_MISMATCH;
+						goto chk_exit;
+			}
+			else
+			{
+				PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: HW core rev (%lx) and SW core rev (%lx) match. [ OK ]",
+						psSGXFeatures->ui32CoreRev, psSGXFeatures->ui32CoreRevSW));
+			}
+		}
+	}
+
+
+	psSGXStructSizes = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXStructSizes;
+
+	bStructSizesFailed = IMG_FALSE;
+
+	CHECK_SIZE(HOST_CTL);
+	CHECK_SIZE(COMMAND);
+#if defined(SGX_FEATURE_2D_HARDWARE)
+	CHECK_SIZE(2DCMD);
+	CHECK_SIZE(2DCMD_SHARED);
+#endif
+	CHECK_SIZE(CMDTA);
+	CHECK_SIZE(CMDTA_SHARED);
+	CHECK_SIZE(TRANSFERCMD);
+	CHECK_SIZE(TRANSFERCMD_SHARED);
+
+	CHECK_SIZE(3DREGISTERS);
+	CHECK_SIZE(HWPBDESC);
+	CHECK_SIZE(HWRENDERCONTEXT);
+	CHECK_SIZE(HWRENDERDETAILS);
+	CHECK_SIZE(HWRTDATA);
+	CHECK_SIZE(HWRTDATASET);
+	CHECK_SIZE(HWTRANSFERCONTEXT);
+
+	if (bStructSizesFailed == IMG_TRUE)
+	{
+		PVR_LOG(("(FAIL) SGXInit: Mismatch in SGXMKIF structure sizes."));
+		eError = PVRSRV_ERROR_BUILD_MISMATCH;
+		goto chk_exit;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: SGXMKIF structure sizes match. [ OK ]"));
+	}
+
+
+#if defined(DEBUG) || defined (INTERNAL_TEST)
+	/* Workaround: During development, the DEBUG bit can get out of sync, so
+	 * ignore that bit:
+	 */
+	if (0x1 & (SGX_BUILD_OPTIONS)) {
+		ui32BuildOptions = psSGXFeatures->ui32BuildOptions | 0x1;
+	} else {
+		ui32BuildOptions = psSGXFeatures->ui32BuildOptions & 0xfffffffe;
+	}
+#else
+	ui32BuildOptions = psSGXFeatures->ui32BuildOptions;
+#endif
+	if (ui32BuildOptions != (SGX_BUILD_OPTIONS))
+	{
+		ui32BuildOptionsMismatch = ui32BuildOptions ^ (SGX_BUILD_OPTIONS);
+		if ( ((SGX_BUILD_OPTIONS) & ui32BuildOptionsMismatch) != 0)
+		{
+			PVR_LOG(("(FAIL) SGXInit: Mismatch in driver and microkernel build options; "
+				"extra options present in driver: (0x%lx). Please check sgx_options.h",
+				(SGX_BUILD_OPTIONS) & ui32BuildOptionsMismatch ));
+		}
+
+		if ( (ui32BuildOptions & ui32BuildOptionsMismatch) != 0)
+		{
+			PVR_LOG(("(FAIL) SGXInit: Mismatch in driver and microkernel build options; "
+				"extra options present in microkernel: (0x%lx). Please check sgx_options.h",
+				ui32BuildOptions & ui32BuildOptionsMismatch ));
+		}
+		eError = PVRSRV_ERROR_BUILD_MISMATCH;
+		goto chk_exit;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: Driver and microkernel build options match. [ OK ]"));
+	}
+#endif
+
+	eError = PVRSRV_OK;
+chk_exit:
+#if defined(IGNORE_SGX_INIT_COMPATIBILITY_CHECK)
+	return PVRSRV_OK;
+#else
+	return eError;
+#endif
+}
+
+static
+PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO	*psDevInfo,
+								   PVRSRV_DEVICE_NODE 	*psDeviceNode)
+{
+	PVRSRV_ERROR		eError;
+	SGXMKIF_COMMAND		sCommandData;
+	PVRSRV_SGX_MISCINFO_INFO			*psSGXMiscInfoInt;
+	PVRSRV_SGX_MISCINFO_FEATURES		*psSGXFeatures;
+	SGX_MISCINFO_STRUCT_SIZES			*psSGXStructSizes;
+
+	PPVRSRV_KERNEL_MEM_INFO	psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
+	if (! psMemInfo->pvLinAddrKM)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Invalid address."));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
+	psSGXFeatures = &psSGXMiscInfoInt->sSGXFeatures;
+	psSGXStructSizes = &psSGXMiscInfoInt->sSGXStructSizes;
+
+	psSGXMiscInfoInt->ui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_READY;
+
+
+	OSMemSet(psSGXFeatures, 0, sizeof(*psSGXFeatures));
+	OSMemSet(psSGXStructSizes, 0, sizeof(*psSGXStructSizes));
+
+
+	sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr;
+
+	eError = SGXScheduleCCBCommandKM(psDeviceNode,
+									 SGXMKIF_CMD_GETMISCINFO,
+									 &sCommandData,
+									 KERNEL_ID,
+									 0);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: SGXScheduleCCBCommandKM failed."));
+		return eError;
+	}
+
+
+#if !defined(NO_HARDWARE)
+	{
+		IMG_BOOL bExit;
+
+		bExit = IMG_FALSE;
+		LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+		{
+			if ((psSGXMiscInfoInt->ui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_READY) != 0)
+			{
+				bExit = IMG_TRUE;
+				break;
+			}
+		} END_LOOP_UNTIL_TIMEOUT();
+
+
+		if (!bExit)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Timeout occurred waiting for misc info."));
+			return PVRSRV_ERROR_TIMEOUT;
+		}
+	}
+#endif
+
+	return PVRSRV_OK;
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO	*psDevInfo,
+							  SGX_MISC_INFO			*psMiscInfo,
+							  PVRSRV_DEVICE_NODE 	*psDeviceNode,
+							  IMG_HANDLE 			 hDevMemContext)
+{
+	PPVRSRV_KERNEL_MEM_INFO	psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+	IMG_UINT32	*pui32MiscInfoFlags = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->ui32MiscInfoFlags;
+
+
+	*pui32MiscInfoFlags = 0;
+
+#if !defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+	PVR_UNREFERENCED_PARAMETER(hDevMemContext);
+#endif
+
+	switch(psMiscInfo->eRequest)
+	{
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+		case SGX_MISC_INFO_REQUEST_SET_BREAKPOINT:
+		{
+			IMG_UINT32 ui32RegOffset;
+			IMG_UINT32 ui32RegVal;
+			IMG_UINT32 ui32BaseRegOffset;
+			IMG_UINT32 ui32BaseRegVal;
+			IMG_UINT32 ui32MaskRegOffset;
+			IMG_UINT32 ui32MaskRegVal;
+
+			switch(psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex)
+			{
+				case 0:
+					ui32RegOffset = EUR_CR_BREAKPOINT0;
+					ui32BaseRegOffset = EUR_CR_BREAKPOINT0_BASE;
+					ui32MaskRegOffset = EUR_CR_BREAKPOINT0_MASK;
+					break;
+				case 1:
+					ui32RegOffset = EUR_CR_BREAKPOINT1;
+					ui32BaseRegOffset = EUR_CR_BREAKPOINT1_BASE;
+					ui32MaskRegOffset = EUR_CR_BREAKPOINT1_MASK;
+					break;
+				case 2:
+					ui32RegOffset = EUR_CR_BREAKPOINT2;
+					ui32BaseRegOffset = EUR_CR_BREAKPOINT2_BASE;
+					ui32MaskRegOffset = EUR_CR_BREAKPOINT2_MASK;
+					break;
+				case 3:
+					ui32RegOffset = EUR_CR_BREAKPOINT3;
+					ui32BaseRegOffset = EUR_CR_BREAKPOINT3_BASE;
+					ui32MaskRegOffset = EUR_CR_BREAKPOINT3_MASK;
+					break;
+				default:
+					PVR_DPF((PVR_DBG_ERROR,"SGXGetMiscInfoKM: SGX_MISC_INFO_REQUEST_SET_BREAKPOINT invalid BP idx %d", psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex));
+					return PVRSRV_ERROR_INVALID_PARAMS;
+			}
+
+
+			if(psMiscInfo->uData.sSGXBreakpointInfo.bBPEnable)
+			{
+
+				IMG_DEV_VIRTADDR sBPDevVAddr = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddr;
+
+
+				ui32MaskRegVal = EUR_CR_BREAKPOINT0_MASK_REGION_MASK | EUR_CR_BREAKPOINT0_MASK_DM_MASK;
+
+
+				ui32BaseRegVal = sBPDevVAddr.uiAddr & EUR_CR_BREAKPOINT0_BASE_ADDRESS_MASK;
+
+
+				ui32RegVal =	EUR_CR_BREAKPOINT0_CTRL_WENABLE_MASK
+							|	EUR_CR_BREAKPOINT0_CTRL_WENABLE_MASK
+							|	EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_MASK;
+			}
+			else
+			{
+
+				ui32RegVal = ui32BaseRegVal = ui32MaskRegVal = 0;
+			}
+
+
+
+
+
+
+
+
+
+
+			return PVRSRV_OK;
+		}
+#endif
+
+		case SGX_MISC_INFO_REQUEST_CLOCKSPEED:
+		{
+			psMiscInfo->uData.ui32SGXClockSpeed = psDevInfo->ui32CoreClockSpeed;
+			return PVRSRV_OK;
+		}
+
+		case SGX_MISC_INFO_REQUEST_SGXREV:
+		{
+			PVRSRV_ERROR eError;
+			PVRSRV_SGX_MISCINFO_FEATURES		*psSGXFeatures;
+
+			eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode);
+			if(eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "An error occurred in SGXGetMiscInfoUkernel: %d\n",
+						eError));
+				return eError;
+			}
+			psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+
+			psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+
+
+			PVR_DPF((PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: Core 0x%lx, sw ID 0x%lx, sw Rev 0x%lx\n",
+					psSGXFeatures->ui32CoreRev,
+					psSGXFeatures->ui32CoreIdSW,
+					psSGXFeatures->ui32CoreRevSW));
+			PVR_DPF((PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: DDK version 0x%lx, DDK build 0x%lx\n",
+					psSGXFeatures->ui32DDKVersion,
+					psSGXFeatures->ui32DDKBuild));
+
+
+			return PVRSRV_OK;
+		}
+
+		case SGX_MISC_INFO_REQUEST_DRIVER_SGXREV:
+		{
+			PVRSRV_SGX_MISCINFO_FEATURES		*psSGXFeatures;
+
+			psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+
+			OSMemSet(psMemInfo->pvLinAddrKM, 0,
+					sizeof(PVRSRV_SGX_MISCINFO_INFO));
+
+			psSGXFeatures->ui32DDKVersion =
+				(PVRVERSION_MAJ << 16) |
+				(PVRVERSION_MIN << 8) |
+				PVRVERSION_BRANCH;
+			psSGXFeatures->ui32DDKBuild = PVRVERSION_BUILD;
+
+
+			psSGXFeatures->ui32BuildOptions = (SGX_BUILD_OPTIONS);
+
+
+			psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+			return PVRSRV_OK;
+		}
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+		case SGX_MISC_INFO_REQUEST_MEMREAD:
+		{
+			PVRSRV_ERROR eError;
+			PPVRSRV_KERNEL_MEM_INFO	psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+			PVRSRV_SGX_MISCINFO_FEATURES		*psSGXFeatures;
+			PVRSRV_SGX_MISCINFO_MEMREAD			*psSGXMemReadData;
+
+			psSGXMemReadData = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemReadData;
+
+
+			*pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMREAD;
+
+
+			if(psMiscInfo->hDevMemContext != IMG_NULL)
+			{
+				SGXGetMMUPDAddrKM( (IMG_HANDLE)psDeviceNode, hDevMemContext, &psSGXMemReadData->sPDDevPAddr);
+			}
+			else
+			{
+				return PVRSRV_ERROR_INVALID_PARAMS;
+			}
+
+
+			if(psMiscInfo->sDevVAddr.uiAddr != 0)
+			{
+				psSGXMemReadData->sDevVAddr = psMiscInfo->sDevVAddr;
+			}
+			else
+			{
+				return PVRSRV_ERROR_INVALID_PARAMS;
+			}
+
+
+			eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode);
+			if(eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "An error occurred in SGXGetMiscInfoUkernel: %d\n",
+						eError));
+				return eError;
+			}
+			psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+#if !defined SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+			if(*pui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_MEMREAD_FAIL)
+			{
+				return PVRSRV_ERROR_GENERIC;
+			}
+#endif
+
+			psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+			return PVRSRV_OK;
+		}
+#endif
+
+#ifdef SUPPORT_SGX_HWPERF
+		case SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS:
+		{
+			SGXMKIF_HWPERF_CB *psHWPerfCB = psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+			IMG_UINT ui32MatchingFlags;
+
+
+			if ((psMiscInfo->uData.ui32NewHWPerfStatus & ~(PVRSRV_SGX_HWPERF_GRAPHICS_ON | PVRSRV_SGX_HWPERF_MK_EXECUTION_ON)) != 0)
+			{
+				return PVRSRV_ERROR_INVALID_PARAMS;
+			}
+
+
+			ui32MatchingFlags = psMiscInfo->uData.ui32NewHWPerfStatus & psDevInfo->psSGXHostCtl->ui32HWPerfFlags;
+			if((ui32MatchingFlags & PVRSRV_SGX_HWPERF_GRAPHICS_ON) == 0UL)
+			{
+				psHWPerfCB->ui32OrdinalGRAPHICS = 0xffffffff;
+			}
+			if((ui32MatchingFlags & PVRSRV_SGX_HWPERF_MK_EXECUTION_ON) == 0UL)
+			{
+				psHWPerfCB->ui32OrdinalMK_EXECUTION = 0xffffffffUL;
+			}
+
+
+			psDevInfo->psSGXHostCtl->ui32HWPerfFlags = psMiscInfo->uData.ui32NewHWPerfStatus;
+			#if defined(PDUMP)
+			PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX ukernel HWPerf status %lu\n",
+								  psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
+			PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+					 offsetof(SGXMKIF_HOST_CTL, ui32HWPerfFlags),
+					 sizeof(psDevInfo->psSGXHostCtl->ui32HWPerfFlags), PDUMP_FLAGS_CONTINUOUS,
+					 MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+			#endif
+
+			return PVRSRV_OK;
+		}
+		case SGX_MISC_INFO_REQUEST_HWPERF_CB_ON:
+		{
+
+			SGXMKIF_HWPERF_CB *psHWPerfCB = psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+			psHWPerfCB->ui32OrdinalGRAPHICS = 0xffffffffUL;
+
+			psDevInfo->psSGXHostCtl->ui32HWPerfFlags |= PVRSRV_SGX_HWPERF_GRAPHICS_ON;
+			return PVRSRV_OK;
+		}
+		case SGX_MISC_INFO_REQUEST_HWPERF_CB_OFF:
+		{
+
+			psDevInfo->psSGXHostCtl->ui32HWPerfFlags = 0;
+			return PVRSRV_OK;
+		}
+		case SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB:
+		{
+
+			SGX_MISC_INFO_HWPERF_RETRIEVE_CB *psRetrieve = &psMiscInfo->uData.sRetrieveCB;
+			SGXMKIF_HWPERF_CB *psHWPerfCB = psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+			IMG_UINT i;
+
+			for (i = 0; psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff && i < psRetrieve->ui32ArraySize; i++)
+			{
+				SGXMKIF_HWPERF_CB_ENTRY *psData = &psHWPerfCB->psHWPerfCBData[psHWPerfCB->ui32Roff];
+
+
+
+				psRetrieve->psHWPerfData[i].ui32FrameNo = psData->ui32FrameNo;
+				psRetrieve->psHWPerfData[i].ui32Type = (psData->ui32Type & PVRSRV_SGX_HWPERF_TYPE_OP_MASK);
+				psRetrieve->psHWPerfData[i].ui32StartTime = psData->ui32Time;
+				psRetrieve->psHWPerfData[i].ui32StartTimeWraps = psData->ui32TimeWraps;
+				psRetrieve->psHWPerfData[i].ui32EndTime = psData->ui32Time;
+				psRetrieve->psHWPerfData[i].ui32EndTimeWraps = psData->ui32TimeWraps;
+				psRetrieve->psHWPerfData[i].ui32ClockSpeed = psDevInfo->ui32CoreClockSpeed;
+				psRetrieve->psHWPerfData[i].ui32TimeMax = psDevInfo->ui32uKernelTimerClock;
+				psHWPerfCB->ui32Roff = (psHWPerfCB->ui32Roff + 1) & (SGXMKIF_HWPERF_CB_SIZE - 1);
+			}
+			psRetrieve->ui32DataCount = i;
+			psRetrieve->ui32Time = OSClockus();
+			return PVRSRV_OK;
+		}
+#endif
+		case SGX_MISC_INFO_DUMP_DEBUG_INFO:
+		{
+			PVR_LOG(("User requested SGX debug info"));
+
+
+			SGXDumpDebugInfo(psDeviceNode, IMG_FALSE);
+
+			return PVRSRV_OK;
+		}
+
+		case SGX_MISC_INFO_PANIC:
+		{
+			PVR_LOG(("User requested SGX panic"));
+
+			SGXPanic(psDeviceNode);
+
+			return PVRSRV_OK;
+		}
+
+		default:
+		{
+
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+	}
+}
+
+#if defined(SUPPORT_SGX_HWPERF)
+IMG_EXPORT
+PVRSRV_ERROR SGXReadDiffCountersKM(IMG_HANDLE				hDevHandle,
+								   IMG_UINT32				ui32Reg,
+								   IMG_UINT32				*pui32Old,
+								   IMG_BOOL					bNew,
+								   IMG_UINT32				ui32New,
+								   IMG_UINT32				ui32NewReset,
+								   IMG_UINT32				ui32CountersReg,
+								   IMG_UINT32				ui32Reg2,
+								   IMG_BOOL					*pbActive,
+								   PVRSRV_SGXDEV_DIFF_INFO	*psDiffs)
+{
+	PVRSRV_ERROR    	eError;
+	SYS_DATA			*psSysData;
+	PVRSRV_POWER_DEV	*psPowerDevice;
+	IMG_BOOL			bPowered = IMG_FALSE;
+	PVRSRV_DEVICE_NODE	*psDeviceNode = hDevHandle;
+	PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+
+
+	if(bNew)
+	{
+		psDevInfo->ui32HWGroupRequested = ui32New;
+	}
+	psDevInfo->ui32HWReset |= ui32NewReset;
+
+
+	eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	SysAcquireData(&psSysData);
+
+
+	psPowerDevice = (PVRSRV_POWER_DEV*)
+				List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+											MatchPowerDeviceIndex_AnyVaCb,
+											psDeviceNode->sDevId.ui32DeviceIndex);
+
+	if (psPowerDevice)
+	{
+		bPowered = (IMG_BOOL)(psPowerDevice->eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON);
+	}
+
+
+
+	*pbActive = bPowered;
+
+
+
+	{
+		IMG_UINT32 ui32rval = 0;
+
+
+		if(bPowered)
+		{
+			IMG_UINT32 i;
+
+
+			*pui32Old = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32Reg);
+
+			for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i)
+			{
+				psDiffs->aui32Counters[i] = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32CountersReg + (i * 4));
+			}
+
+			if(ui32Reg2)
+			{
+				ui32rval = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32Reg2);
+			}
+
+
+
+			if (psDevInfo->ui32HWGroupRequested != *pui32Old)
+			{
+
+				if(psDevInfo->ui32HWReset != 0)
+				{
+					OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Reg, psDevInfo->ui32HWGroupRequested | psDevInfo->ui32HWReset);
+					psDevInfo->ui32HWReset = 0;
+				}
+
+				OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Reg, psDevInfo->ui32HWGroupRequested);
+			}
+		}
+
+		psDiffs->ui32Time[0] = OSClockus();
+		psDiffs->ui32Time[1] = psDevInfo->psSGXHostCtl->ui32TimeWraps;
+		psDiffs->ui32Time[2] = ui32rval;
+
+		psDiffs->ui32Marker[0] = psDevInfo->ui32KickTACounter;
+		psDiffs->ui32Marker[1] = psDevInfo->ui32KickTARenderCounter;
+	}
+
+
+	PVRSRVPowerUnlock(KERNEL_ID);
+
+	SGXTestActivePowerEvent(psDeviceNode, KERNEL_ID);
+
+	return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXReadHWPerfCBKM(IMG_HANDLE					hDevHandle,
+							   IMG_UINT32					ui32ArraySize,
+							   PVRSRV_SGX_HWPERF_CB_ENTRY	*psClientHWPerfEntry,
+							   IMG_UINT32					*pui32DataCount,
+							   IMG_UINT32					*pui32ClockSpeed,
+							   IMG_UINT32					*pui32HostTimeStamp)
+{
+	PVRSRV_ERROR    	eError = PVRSRV_OK;
+	PVRSRV_DEVICE_NODE	*psDeviceNode = hDevHandle;
+	PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+	SGXMKIF_HWPERF_CB	*psHWPerfCB = psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+	IMG_UINT			i;
+
+	for (i = 0;
+		 psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff && i < ui32ArraySize;
+		 i++)
+	{
+		SGXMKIF_HWPERF_CB_ENTRY *psMKPerfEntry = &psHWPerfCB->psHWPerfCBData[psHWPerfCB->ui32Roff];
+
+		psClientHWPerfEntry[i].ui32FrameNo = psMKPerfEntry->ui32FrameNo;
+		psClientHWPerfEntry[i].ui32Type = psMKPerfEntry->ui32Type;
+		psClientHWPerfEntry[i].ui32Ordinal	= psMKPerfEntry->ui32Ordinal;
+		psClientHWPerfEntry[i].ui32Clocksx16 = SGXConvertTimeStamp(psDevInfo,
+													psMKPerfEntry->ui32TimeWraps,
+													psMKPerfEntry->ui32Time);
+		OSMemCopy(&psClientHWPerfEntry[i].ui32Counters[0],
+				  &psMKPerfEntry->ui32Counters[0],
+				  sizeof(psMKPerfEntry->ui32Counters));
+
+		psHWPerfCB->ui32Roff = (psHWPerfCB->ui32Roff + 1) & (SGXMKIF_HWPERF_CB_SIZE - 1);
+	}
+
+	*pui32DataCount = i;
+	*pui32ClockSpeed = psDevInfo->ui32CoreClockSpeed;
+	*pui32HostTimeStamp = OSClockus();
+
+	return eError;
+}
+#else
+#endif
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxkick.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxkick.c
new file mode 100644
index 0000000..575ca69
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxkick.c
@@ -0,0 +1,740 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <stddef.h>
+#include "services_headers.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#if defined (PDUMP)
+#include "sgxapi_km.h"
+#include "pdump_km.h"
+#endif
+#include "sgx_bridge_km.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+
+IMG_EXPORT
+PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_KERNEL_SYNC_INFO	*psSyncInfo;
+	PVRSRV_KERNEL_MEM_INFO	*psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *) psCCBKick->hCCBKernelMemInfo;
+	SGXMKIF_CMDTA_SHARED *psTACmd;
+	IMG_UINT32 i;
+#if defined(SUPPORT_SGX_HWPERF)
+	PVRSRV_DEVICE_NODE      *psDeviceNode;
+	PVRSRV_SGXDEV_INFO      *psDevInfo;
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
+	psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+	if (psCCBKick->bKickRender)
+	{
+		++psDevInfo->ui32KickTARenderCounter;
+	}
+	++psDevInfo->ui32KickTACounter;
+#endif
+
+	if (!CCB_OFFSET_IS_VALID(SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXDoKickKM: Invalid CCB offset"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+
+	psTACmd = CCB_DATA_FROM_OFFSET(SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset);
+
+
+	if (psCCBKick->hTA3DSyncInfo)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+		psTACmd->sTA3DDependency.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+		psTACmd->sTA3DDependency.ui32WriteOpsPendingVal   = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+		if (psCCBKick->bTADependency)
+		{
+			psSyncInfo->psSyncData->ui32WriteOpsPending++;
+		}
+	}
+
+	if (psCCBKick->hTASyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+
+		psTACmd->sTATQSyncReadOpsCompleteDevVAddr  = psSyncInfo->sReadOpsCompleteDevVAddr;
+		psTACmd->sTATQSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+		psTACmd->ui32TATQSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+		psTACmd->ui32TATQSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+	}
+
+	if (psCCBKick->h3DSyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+
+		psTACmd->s3DTQSyncReadOpsCompleteDevVAddr  = psSyncInfo->sReadOpsCompleteDevVAddr;
+		psTACmd->s3DTQSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+		psTACmd->ui323DTQSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+		psTACmd->ui323DTQSyncWriteOpsPendingVal  = psSyncInfo->psSyncData->ui32WriteOpsPending;
+	}
+
+	psTACmd->ui32NumTAStatusVals = psCCBKick->ui32NumTAStatusVals;
+	if (psCCBKick->ui32NumTAStatusVals != 0)
+	{
+
+		for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+		{
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+			psTACmd->sCtlTAStatusInfo[i] = psCCBKick->asTAStatusUpdate[i].sCtlStatus;
+#else
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+			psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+			psTACmd->sCtlTAStatusInfo[i].ui32StatusValue = psSyncInfo->psSyncData->ui32ReadOpsPending;
+#endif
+		}
+	}
+
+	psTACmd->ui32Num3DStatusVals = psCCBKick->ui32Num3DStatusVals;
+	if (psCCBKick->ui32Num3DStatusVals != 0)
+	{
+
+		for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+		{
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+			psTACmd->sCtl3DStatusInfo[i] = psCCBKick->as3DStatusUpdate[i].sCtlStatus;
+#else
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+			psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+			psTACmd->sCtl3DStatusInfo[i].ui32StatusValue = psSyncInfo->psSyncData->ui32ReadOpsPending;
+#endif
+		}
+	}
+
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+	psTACmd->ui32NumTASrcSyncs = psCCBKick->ui32NumTASrcSyncs;
+	for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+
+		psTACmd->asTASrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+		psTACmd->asTASrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+
+		psTACmd->asTASrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+		psTACmd->asTASrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+	}
+
+	psTACmd->ui32NumTADstSyncs = psCCBKick->ui32NumTADstSyncs;
+	for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+
+		psTACmd->asTADstSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+		psTACmd->asTADstSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+
+		psTACmd->asTADstSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+		psTACmd->asTADstSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+	}
+
+	psTACmd->ui32Num3DSrcSyncs = psCCBKick->ui32Num3DSrcSyncs;
+	for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+
+		psTACmd->as3DSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+		psTACmd->as3DSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+
+		psTACmd->as3DSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+		psTACmd->as3DSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+	}
+#else
+
+	psTACmd->ui32NumSrcSyncs = psCCBKick->ui32NumSrcSyncs;
+	for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+
+		psTACmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+		psTACmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+
+		psTACmd->asSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+		psTACmd->asSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+	}
+#endif
+
+	if (psCCBKick->bFirstKickOrResume && psCCBKick->ui32NumDstSyncObjects > 0)
+	{
+		PVRSRV_KERNEL_MEM_INFO	*psHWDstSyncListMemInfo =
+								(PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo;
+		SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList = psHWDstSyncListMemInfo->pvLinAddrKM;
+		IMG_UINT32	ui32NumDstSyncs = psCCBKick->ui32NumDstSyncObjects;
+
+		PVR_ASSERT(((PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo)->ui32AllocSize >= (sizeof(SGXMKIF_HWDEVICE_SYNC_LIST) +
+								(sizeof(PVRSRV_DEVICE_SYNC_OBJECT) * ui32NumDstSyncs)));
+
+		psHWDeviceSyncList->ui32NumSyncObjects = ui32NumDstSyncs;
+#if defined(PDUMP)
+		if (PDumpIsCaptureFrameKM())
+		{
+			PDUMPCOMMENT("HWDeviceSyncList for TACmd\r\n");
+			PDUMPMEM(IMG_NULL,
+					 psHWDstSyncListMemInfo,
+					 0,
+					 sizeof(SGXMKIF_HWDEVICE_SYNC_LIST),
+					 0,
+					 MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+		}
+#endif
+
+		for (i=0; i<ui32NumDstSyncs; i++)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
+
+			if (psSyncInfo)
+			{
+				psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+				psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+				psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+				psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+
+	#if defined(PDUMP)
+				if (PDumpIsCaptureFrameKM())
+				{
+					IMG_UINT32 ui32ModifiedValue;
+					IMG_UINT32 ui32SyncOffset = offsetof(SGXMKIF_HWDEVICE_SYNC_LIST, asSyncData)
+												+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT));
+					IMG_UINT32 ui32WOpsOffset = ui32SyncOffset
+												+ offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal);
+					IMG_UINT32 ui32ROpsOffset = ui32SyncOffset
+												+ offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal);
+
+					PDUMPCOMMENT("HWDeviceSyncObject for RT: %i\r\n", i);
+
+					PDUMPMEM(IMG_NULL,
+							 psHWDstSyncListMemInfo,
+							 ui32SyncOffset,
+							 sizeof(PVRSRV_DEVICE_SYNC_OBJECT),
+							 0,
+							 MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+					if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+						(psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+					{
+
+						PDUMPCOMMENT("Init RT ROpsComplete\r\n", i);
+						PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+							psSyncInfo->psSyncDataMemInfoKM,
+							offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+							sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+							0,
+							MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+						PDUMPCOMMENT("Init RT WOpsComplete\r\n");
+							PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+								psSyncInfo->psSyncDataMemInfoKM,
+								offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+								sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+								0,
+								MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+					}
+
+					psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+
+					ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastOpDumpVal - 1;
+
+					PDUMPCOMMENT("Modify RT %d WOpPendingVal in HWDevSyncList\r\n", i);
+
+					PDUMPMEM(&ui32ModifiedValue,
+						psHWDstSyncListMemInfo,
+						ui32WOpsOffset,
+						sizeof(IMG_UINT32),
+						0,
+						MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+					ui32ModifiedValue = 0;
+					PDUMPCOMMENT("Modify RT %d ROpsPendingVal in HWDevSyncList\r\n", i);
+
+					PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+						 psHWDstSyncListMemInfo,
+						 ui32ROpsOffset,
+						 sizeof(IMG_UINT32),
+						 0,
+						MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+				}
+	#endif
+			}
+			else
+			{
+				psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr.uiAddr = 0;
+				psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr.uiAddr = 0;
+
+				psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = 0;
+				psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = 0;
+			}
+		}
+	}
+
+
+
+
+	psTACmd->ui32CtrlFlags |= SGXMKIF_CMDTA_CTRLFLAGS_READY;
+
+#if defined(PDUMP)
+	if (PDumpIsCaptureFrameKM())
+	{
+		PDUMPCOMMENT("Shared part of TA command\r\n");
+
+		PDUMPMEM(psTACmd,
+				 psCCBMemInfo,
+				 psCCBKick->ui32CCBDumpWOff,
+				 sizeof(SGXMKIF_CMDTA_SHARED),
+				 0,
+				 MAKEUNIQUETAG(psCCBMemInfo));
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+		for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+		{
+			IMG_UINT32 	ui32ModifiedValue;
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+
+			if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+				(psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+			{
+
+				PDUMPCOMMENT("Init RT TA-SRC ROpsComplete\r\n", i);
+				PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					psSyncInfo->psSyncDataMemInfoKM,
+					offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+					sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+					0,
+					MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+				PDUMPCOMMENT("Init RT TA-SRC WOpsComplete\r\n");
+					PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+						psSyncInfo->psSyncDataMemInfoKM,
+						offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+						sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+						0,
+						MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+			}
+
+			psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+			ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+			PDUMPCOMMENT("Modify TA SrcSync %d ROpsPendingVal\r\n", i);
+
+			PDUMPMEM(&ui32ModifiedValue,
+				 psCCBMemInfo,
+				 psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTASrcSyncs) +
+					(i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+				 sizeof(IMG_UINT32),
+				 0,
+				MAKEUNIQUETAG(psCCBMemInfo));
+
+			PDUMPCOMMENT("Modify TA SrcSync %d WOpPendingVal\r\n", i);
+
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+				psCCBMemInfo,
+				psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTASrcSyncs) +
+					(i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+				sizeof(IMG_UINT32),
+				0,
+				MAKEUNIQUETAG(psCCBMemInfo));
+		}
+
+		for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+		{
+			IMG_UINT32 	ui32ModifiedValue;
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+
+			if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+				(psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+			{
+
+				PDUMPCOMMENT("Init RT TA-DST ROpsComplete\r\n", i);
+				PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					psSyncInfo->psSyncDataMemInfoKM,
+					offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+					sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+					0,
+					MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+				PDUMPCOMMENT("Init RT TA-DST WOpsComplete\r\n");
+					PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+						psSyncInfo->psSyncDataMemInfoKM,
+						offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+						sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+						0,
+						MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+			}
+
+			psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+
+			ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastOpDumpVal - 1;
+
+			PDUMPCOMMENT("Modify TA DstSync %d WOpPendingVal\r\n", i);
+
+			PDUMPMEM(&ui32ModifiedValue,
+				 psCCBMemInfo,
+				 psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTADstSyncs) +
+					(i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+				 sizeof(IMG_UINT32),
+				 0,
+				MAKEUNIQUETAG(psCCBMemInfo));
+
+			PDUMPCOMMENT("Modify TA DstSync %d ROpsPendingVal\r\n", i);
+
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+				psCCBMemInfo,
+				psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTADstSyncs) +
+					(i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+				sizeof(IMG_UINT32),
+				0,
+				MAKEUNIQUETAG(psCCBMemInfo));
+		}
+
+		for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+		{
+			IMG_UINT32 	ui32ModifiedValue;
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+
+			if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+				(psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+			{
+
+				PDUMPCOMMENT("Init RT 3D-SRC ROpsComplete\r\n", i);
+				PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					psSyncInfo->psSyncDataMemInfoKM,
+					offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+					sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+					0,
+					MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+				PDUMPCOMMENT("Init RT 3D-SRC WOpsComplete\r\n");
+					PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+						psSyncInfo->psSyncDataMemInfoKM,
+						offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+						sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+						0,
+						MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+			}
+
+			psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+			ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+			PDUMPCOMMENT("Modify 3D SrcSync %d ROpsPendingVal\r\n", i);
+
+			PDUMPMEM(&ui32ModifiedValue,
+				 psCCBMemInfo,
+				 psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, as3DSrcSyncs) +
+					(i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+				 sizeof(IMG_UINT32),
+				 0,
+				MAKEUNIQUETAG(psCCBMemInfo));
+
+			PDUMPCOMMENT("Modify 3D SrcSync %d WOpPendingVal\r\n", i);
+
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+				psCCBMemInfo,
+				psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, as3DSrcSyncs) +
+					(i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+				sizeof(IMG_UINT32),
+				0,
+				MAKEUNIQUETAG(psCCBMemInfo));
+		}
+#else
+		for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+		{
+			IMG_UINT32 	ui32ModifiedValue;
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+
+			if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+				(psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+			{
+
+				PDUMPCOMMENT("Init RT ROpsComplete\r\n", i);
+				PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					psSyncInfo->psSyncDataMemInfoKM,
+					offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+					sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+					0,
+					MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+				PDUMPCOMMENT("Init RT WOpsComplete\r\n");
+					PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+						psSyncInfo->psSyncDataMemInfoKM,
+						offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+						sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+						0,
+						MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+			}
+
+			psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+			ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+			PDUMPCOMMENT("Modify SrcSync %d ROpsPendingVal\r\n", i);
+
+			PDUMPMEM(&ui32ModifiedValue,
+				 psCCBMemInfo,
+				 psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asSrcSyncs) +
+					(i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+				 sizeof(IMG_UINT32),
+				 0,
+				MAKEUNIQUETAG(psCCBMemInfo));
+
+			PDUMPCOMMENT("Modify SrcSync %d WOpPendingVal\r\n", i);
+
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+				psCCBMemInfo,
+				psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asSrcSyncs) +
+					(i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+				sizeof(IMG_UINT32),
+				0,
+				MAKEUNIQUETAG(psCCBMemInfo));
+		}
+#endif
+
+		for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+		{
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+			PDUMPCOMMENT("Modify TA status value in TA cmd\r\n");
+			PDUMPMEM(&psCCBKick->asTAStatusUpdate[i].ui32LastStatusUpdateDumpVal,
+				 psCCBMemInfo,
+				 psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, sCtlTAStatusInfo[i].ui32StatusValue),
+				 sizeof(IMG_UINT32),
+				 0,
+				MAKEUNIQUETAG(psCCBMemInfo));
+#else
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+			PDUMPCOMMENT("Modify TA status value in TA cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+				 psCCBMemInfo,
+				 psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, sCtlTAStatusInfo[i].ui32StatusValue),
+				 sizeof(IMG_UINT32),
+				 0,
+				MAKEUNIQUETAG(psCCBMemInfo));
+#endif
+		}
+
+		for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+		{
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+			PDUMPCOMMENT("Modify 3D status value in TA cmd\r\n");
+			PDUMPMEM(&psCCBKick->as3DStatusUpdate[i].ui32LastStatusUpdateDumpVal,
+				 psCCBMemInfo,
+				 psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, sCtl3DStatusInfo[i].ui32StatusValue),
+				 sizeof(IMG_UINT32),
+				 0,
+				MAKEUNIQUETAG(psCCBMemInfo));
+#else
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+			PDUMPCOMMENT("Modify 3D status value in TA cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+				 psCCBMemInfo,
+				 psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, sCtl3DStatusInfo[i].ui32StatusValue),
+				 sizeof(IMG_UINT32),
+				 0,
+				MAKEUNIQUETAG(psCCBMemInfo));
+#endif
+		}
+	}
+#endif
+
+	eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_TA, &psCCBKick->sCommand, KERNEL_ID, 0);
+	if (eError == PVRSRV_ERROR_RETRY)
+	{
+		if (psCCBKick->bFirstKickOrResume && psCCBKick->ui32NumDstSyncObjects > 0)
+		{
+			for (i=0; i < psCCBKick->ui32NumDstSyncObjects; i++)
+			{
+
+				psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
+
+				if (psSyncInfo)
+				{
+					psSyncInfo->psSyncData->ui32WriteOpsPending--;
+#if defined(PDUMP)
+					if (PDumpIsCaptureFrameKM())
+					{
+						psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+					}
+#endif
+				}
+			}
+		}
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+		for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+			psSyncInfo->psSyncData->ui32ReadOpsPending--;
+		}
+		for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+			psSyncInfo->psSyncData->ui32WriteOpsPending--;
+		}
+		for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+			psSyncInfo->psSyncData->ui32ReadOpsPending--;
+		}
+#else
+		for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+			psSyncInfo->psSyncData->ui32ReadOpsPending--;
+		}
+#endif
+
+		return eError;
+	}
+	else if (PVRSRV_OK != eError)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXDoKickKM: SGXScheduleCCBCommandKM failed."));
+		return eError;
+	}
+
+
+#if defined(NO_HARDWARE)
+
+
+
+	if (psCCBKick->hTA3DSyncInfo)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+
+		if (psCCBKick->bTADependency)
+		{
+			psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+		}
+	}
+
+	if (psCCBKick->hTASyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+
+		psSyncInfo->psSyncData->ui32ReadOpsComplete =  psSyncInfo->psSyncData->ui32ReadOpsPending;
+	}
+
+	if (psCCBKick->h3DSyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+
+		psSyncInfo->psSyncData->ui32ReadOpsComplete =  psSyncInfo->psSyncData->ui32ReadOpsPending;
+	}
+
+
+	for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+	{
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+		PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->asTAStatusUpdate[i].hKernelMemInfo;
+
+		*(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM
+						+ (psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr.uiAddr
+						- psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
+#else
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+		psSyncInfo->psSyncData->ui32ReadOpsComplete = psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
+#endif
+	}
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+	for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+		psSyncInfo->psSyncData->ui32ReadOpsComplete =  psSyncInfo->psSyncData->ui32ReadOpsPending;
+	}
+	for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+		psSyncInfo->psSyncData->ui32WriteOpsComplete =  psSyncInfo->psSyncData->ui32WriteOpsPending;
+	}
+	for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+		psSyncInfo->psSyncData->ui32ReadOpsComplete =  psSyncInfo->psSyncData->ui32ReadOpsPending;
+	}
+#else
+
+	for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+		psSyncInfo->psSyncData->ui32ReadOpsComplete =  psSyncInfo->psSyncData->ui32ReadOpsPending;
+	}
+#endif
+
+	if (psCCBKick->bTerminateOrAbort)
+	{
+		if (psCCBKick->ui32NumDstSyncObjects > 0)
+		{
+			PVRSRV_KERNEL_MEM_INFO	*psHWDstSyncListMemInfo =
+								(PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo;
+			SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList = psHWDstSyncListMemInfo->pvLinAddrKM;
+
+			for (i=0; i<psCCBKick->ui32NumDstSyncObjects; i++)
+			{
+				psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
+				if (psSyncInfo)
+					psSyncInfo->psSyncData->ui32WriteOpsComplete = psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal+1;
+			}
+		}
+
+
+		for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+		{
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+			PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->as3DStatusUpdate[i].hKernelMemInfo;
+
+			*(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM
+							+ (psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr.uiAddr
+							- psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;
+#else
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+			psSyncInfo->psSyncData->ui32ReadOpsComplete = psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;
+#endif
+		}
+	}
+#endif
+
+	return eError;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxpower.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxpower.c
new file mode 100644
index 0000000..af4d52a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxpower.c
@@ -0,0 +1,465 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "sgxapi_km.h"
+#include "sgx_mkif_km.h"
+#include "sgxutils.h"
+#include "pdump_km.h"
+
+
+#if defined(SUPPORT_HW_RECOVERY)
+static PVRSRV_ERROR SGXAddTimer(PVRSRV_DEVICE_NODE		*psDeviceNode,
+								SGX_TIMING_INFORMATION	*psSGXTimingInfo,
+								IMG_HANDLE				*phTimer)
+{
+
+
+
+	*phTimer = OSAddTimer(SGXOSTimer, psDeviceNode,
+						  1000 * 50 / psSGXTimingInfo->ui32uKernelFreq);
+	if(*phTimer == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXAddTimer : Failed to register timer callback function"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	return PVRSRV_OK;
+}
+#endif
+
+
+static PVRSRV_ERROR SGXUpdateTimingInfo(PVRSRV_DEVICE_NODE	*psDeviceNode)
+{
+	PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+	SGX_TIMING_INFORMATION	sSGXTimingInfo = {0};
+#else
+	SGX_DEVICE_MAP		*psSGXDeviceMap;
+#endif
+	IMG_UINT32		ui32ActivePowManSampleRate;
+	SGX_TIMING_INFORMATION	*psSGXTimingInfo;
+
+
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+	psSGXTimingInfo = &sSGXTimingInfo;
+	SysGetSGXTimingInformation(psSGXTimingInfo);
+#else
+	SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+						  (IMG_VOID**)&psSGXDeviceMap);
+	psSGXTimingInfo = &psSGXDeviceMap->sTimingInfo;
+#endif
+
+#if defined(SUPPORT_HW_RECOVERY)
+	{
+		PVRSRV_ERROR			eError;
+		IMG_UINT32	ui32OlduKernelFreq;
+
+		if (psDevInfo->hTimer != IMG_NULL)
+		{
+			ui32OlduKernelFreq = psDevInfo->ui32CoreClockSpeed / psDevInfo->ui32uKernelTimerClock;
+			if (ui32OlduKernelFreq != psSGXTimingInfo->ui32uKernelFreq)
+			{
+
+
+				IMG_HANDLE hNewTimer;
+
+				eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &hNewTimer);
+				if (eError == PVRSRV_OK)
+				{
+					eError = OSRemoveTimer(psDevInfo->hTimer);
+					if (eError != PVRSRV_OK)
+					{
+						PVR_DPF((PVR_DBG_ERROR,"SGXUpdateTimingInfo: Failed to remove timer"));
+					}
+					psDevInfo->hTimer = hNewTimer;
+				}
+				else
+				{
+
+				}
+			}
+		}
+		else
+		{
+			eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &psDevInfo->hTimer);
+			if (eError != PVRSRV_OK)
+			{
+				return eError;
+			}
+		}
+
+		psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate =
+			psSGXTimingInfo->ui32uKernelFreq / psSGXTimingInfo->ui32HWRecoveryFreq;
+	}
+#endif
+
+
+	psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed;
+	psDevInfo->ui32uKernelTimerClock = psSGXTimingInfo->ui32CoreClockSpeed / psSGXTimingInfo->ui32uKernelFreq;
+
+
+	psDevInfo->psSGXHostCtl->ui32uKernelTimerClock = psDevInfo->ui32uKernelTimerClock;
+#if defined(PDUMP)
+	PDUMPCOMMENT("Host Control - Microkernel clock");
+	PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+			 offsetof(SGXMKIF_HOST_CTL, ui32uKernelTimerClock),
+			 sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+			 MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+#endif
+
+	if (psSGXTimingInfo->bEnableActivePM)
+	{
+		ui32ActivePowManSampleRate =
+			psSGXTimingInfo->ui32uKernelFreq * psSGXTimingInfo->ui32ActivePowManLatencyms / 1000;
+
+
+
+
+
+
+
+
+		ui32ActivePowManSampleRate += 1;
+	}
+	else
+	{
+		ui32ActivePowManSampleRate = 0;
+	}
+
+	psDevInfo->psSGXHostCtl->ui32ActivePowManSampleRate = ui32ActivePowManSampleRate;
+#if defined(PDUMP)
+	PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+			 offsetof(SGXMKIF_HOST_CTL, ui32ActivePowManSampleRate),
+			 sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+			 MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+#endif
+
+	return PVRSRV_OK;
+}
+
+
+static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO	*psDevInfo)
+{
+	#if defined(SUPPORT_HW_RECOVERY)
+	PVRSRV_ERROR	eError;
+
+	eError = OSEnableTimer(psDevInfo->hTimer);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXStartTimer : Failed to enable host timer"));
+	}
+	#else
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+	#endif
+}
+
+
+static IMG_VOID SGXPollForClockGating (PVRSRV_SGXDEV_INFO	*psDevInfo,
+									   IMG_UINT32			ui32Register,
+									   IMG_UINT32			ui32RegisterValue,
+									   IMG_CHAR				*pszComment)
+{
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+	PVR_UNREFERENCED_PARAMETER(ui32Register);
+	PVR_UNREFERENCED_PARAMETER(ui32RegisterValue);
+	PVR_UNREFERENCED_PARAMETER(pszComment);
+
+	#if !defined(NO_HARDWARE)
+	PVR_ASSERT(psDevInfo != IMG_NULL);
+
+
+	if (PollForValueKM((IMG_UINT32 *)psDevInfo->pvRegsBaseKM + (ui32Register >> 2),
+						0,
+						ui32RegisterValue,
+						MAX_HW_TIME_US/WAIT_TRY_COUNT,
+						WAIT_TRY_COUNT) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: %s failed.", pszComment));
+	}
+	#endif
+
+	PDUMPCOMMENT(pszComment);
+	PDUMPREGPOL(ui32Register, 0, ui32RegisterValue);
+}
+
+
+PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE				hDevHandle,
+							   PVRSRV_DEV_POWER_STATE	eNewPowerState,
+							   PVRSRV_DEV_POWER_STATE	eCurrentPowerState)
+{
+	if ((eNewPowerState != eCurrentPowerState) &&
+		(eNewPowerState != PVRSRV_DEV_POWER_STATE_ON))
+	{
+		PVRSRV_ERROR		eError;
+		PVRSRV_DEVICE_NODE	*psDeviceNode = hDevHandle;
+		PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+		IMG_UINT32			ui32PowerCmd, ui32CompleteStatus;
+		SGXMKIF_COMMAND		sCommand = {0};
+		IMG_UINT32			ui32Core;
+
+		#if defined(SUPPORT_HW_RECOVERY)
+
+		eError = OSDisableTimer(psDevInfo->hTimer);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to disable timer"));
+			return eError;
+		}
+		#endif
+
+		if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+		{
+
+			ui32PowerCmd = PVRSRV_POWERCMD_POWEROFF;
+			ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE;
+			PDUMPCOMMENT("SGX power off request");
+		}
+		else
+		{
+
+			ui32PowerCmd = PVRSRV_POWERCMD_IDLE;
+			ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE;
+			PDUMPCOMMENT("SGX idle request");
+		}
+
+		sCommand.ui32Data[1] = ui32PowerCmd;
+
+		eError = SGXScheduleCCBCommand(psDevInfo, SGXMKIF_CMD_POWER, &sCommand, KERNEL_ID, 0);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to submit power down command"));
+			return eError;
+		}
+
+
+		#if !defined(NO_HARDWARE)
+		if (PollForValueKM(&psDevInfo->psSGXHostCtl->ui32PowerStatus,
+							ui32CompleteStatus,
+							ui32CompleteStatus,
+							MAX_HW_TIME_US/WAIT_TRY_COUNT,
+							WAIT_TRY_COUNT) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Wait for SGX ukernel power transition failed."));
+			PVR_DBG_BREAK;
+		}
+		#endif
+
+		#if defined(PDUMP)
+		PDUMPCOMMENT("TA/3D CCB Control - Wait for power event on uKernel.");
+		PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo,
+					offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus),
+					ui32CompleteStatus,
+					ui32CompleteStatus,
+					PDUMP_POLL_OPERATOR_EQUAL,
+					0,
+					MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+		#endif
+
+		for (ui32Core = 0; ui32Core < SGX_FEATURE_MP_CORE_COUNT; ui32Core++)
+		{
+
+			SGXPollForClockGating(psDevInfo,
+								  SGX_MP_CORE_SELECT(psDevInfo->ui32ClkGateStatusReg, ui32Core),
+								  psDevInfo->ui32ClkGateStatusMask,
+								  "Wait for SGX clock gating");
+		}
+
+		#if defined(SGX_FEATURE_MP)
+
+		SGXPollForClockGating(psDevInfo,
+							  psDevInfo->ui32MasterClkGateStatusReg,
+							  psDevInfo->ui32MasterClkGateStatusMask,
+							  "Wait for SGX master clock gating");
+		#endif
+
+		if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+		{
+
+			eError = SGXDeinitialise(psDevInfo);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: SGXDeinitialise failed: %lu", eError));
+				return eError;
+			}
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SGXPostPowerState (IMG_HANDLE				hDevHandle,
+								PVRSRV_DEV_POWER_STATE	eNewPowerState,
+								PVRSRV_DEV_POWER_STATE	eCurrentPowerState)
+{
+	if ((eNewPowerState != eCurrentPowerState) &&
+		(eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON))
+	{
+		PVRSRV_ERROR		eError;
+		PVRSRV_DEVICE_NODE	*psDeviceNode = hDevHandle;
+		PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+		SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+
+		psSGXHostCtl->ui32PowerStatus = 0;
+		#if defined(PDUMP)
+		PDUMPCOMMENT("TA/3D CCB Control - Reset power status");
+		PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+				 offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus),
+				 sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+				 MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+		#endif
+
+		if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+		{
+
+
+
+
+
+			eError = SGXUpdateTimingInfo(psDeviceNode);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed"));
+				return eError;
+			}
+
+
+
+			eError = SGXInitialise(psDevInfo);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXInitialise failed"));
+				return eError;
+			}
+		}
+		else
+		{
+
+
+			SGXMKIF_COMMAND		sCommand = {0};
+
+			sCommand.ui32Data[1] = PVRSRV_POWERCMD_RESUME;
+			eError = SGXScheduleCCBCommand(psDevInfo, SGXMKIF_CMD_POWER, &sCommand, ISR_ID, 0);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState failed to schedule CCB command: %lu", eError));
+				return PVRSRV_ERROR_GENERIC;
+			}
+		}
+
+		SGXStartTimer(psDevInfo);
+	}
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SGXPreClockSpeedChange (IMG_HANDLE				hDevHandle,
+									 IMG_BOOL				bIdleDevice,
+									 PVRSRV_DEV_POWER_STATE	eCurrentPowerState)
+{
+	PVRSRV_ERROR		eError;
+	PVRSRV_DEVICE_NODE	*psDeviceNode = hDevHandle;
+	PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+	if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON)
+	{
+		if (bIdleDevice)
+		{
+
+			PDUMPSUSPEND();
+
+			eError = SGXPrePowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_IDLE,
+									  PVRSRV_DEV_POWER_STATE_ON);
+
+			if (eError != PVRSRV_OK)
+			{
+				PDUMPRESUME();
+				return eError;
+			}
+		}
+	}
+
+	PVR_DPF((PVR_DBG_MESSAGE,"SGXPreClockSpeedChange: SGX clock speed was %luHz",
+			psDevInfo->ui32CoreClockSpeed));
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SGXPostClockSpeedChange (IMG_HANDLE				hDevHandle,
+									  IMG_BOOL					bIdleDevice,
+									  PVRSRV_DEV_POWER_STATE	eCurrentPowerState)
+{
+	PVRSRV_DEVICE_NODE	*psDeviceNode = hDevHandle;
+	PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+	IMG_UINT32			ui32OldClockSpeed = psDevInfo->ui32CoreClockSpeed;
+
+	PVR_UNREFERENCED_PARAMETER(ui32OldClockSpeed);
+
+	if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON)
+	{
+		PVRSRV_ERROR eError;
+
+
+
+		eError = SGXUpdateTimingInfo(psDeviceNode);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed"));
+			return eError;
+		}
+
+		if (bIdleDevice)
+		{
+
+			eError = SGXPostPowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_ON,
+									   PVRSRV_DEV_POWER_STATE_IDLE);
+
+			PDUMPRESUME();
+
+			if (eError != PVRSRV_OK)
+			{
+				return eError;
+			}
+		}
+		else
+		{
+			SGXStartTimer(psDevInfo);
+		}
+
+	}
+
+	PVR_DPF((PVR_DBG_MESSAGE,"SGXPostClockSpeedChange: SGX clock speed changed from %luHz to %luHz",
+			ui32OldClockSpeed, psDevInfo->ui32CoreClockSpeed));
+
+	return PVRSRV_OK;
+}
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxreset.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxreset.c
new file mode 100644
index 0000000..a746b88
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxreset.c
@@ -0,0 +1,485 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "sgxinfokm.h"
+#include "sgxconfig.h"
+
+#include "pdump_km.h"
+
+
+static IMG_VOID SGXResetSoftReset(PVRSRV_SGXDEV_INFO	*psDevInfo,
+								  IMG_BOOL				bResetBIF,
+								  IMG_UINT32			ui32PDUMPFlags,
+								  IMG_BOOL				bPDump)
+{
+	IMG_UINT32 ui32SoftResetRegVal;
+
+#if defined(SGX_FEATURE_MP)
+	ui32SoftResetRegVal =
+					EUR_CR_MASTER_SOFT_RESET_IPF_RESET_MASK |
+					EUR_CR_MASTER_SOFT_RESET_DPM_RESET_MASK  |
+					EUR_CR_MASTER_SOFT_RESET_VDM_RESET_MASK;
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+	ui32SoftResetRegVal |= EUR_CR_MASTER_SOFT_RESET_SLC_RESET_MASK;
+#endif
+
+	if (bResetBIF)
+	{
+		ui32SoftResetRegVal |= EUR_CR_MASTER_SOFT_RESET_BIF_RESET_MASK;
+	}
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SOFT_RESET, ui32SoftResetRegVal);
+	if (bPDump)
+	{
+		PDUMPREGWITHFLAGS(EUR_CR_MASTER_SOFT_RESET, ui32SoftResetRegVal, ui32PDUMPFlags);
+	}
+#endif
+
+	ui32SoftResetRegVal =
+
+					EUR_CR_SOFT_RESET_DPM_RESET_MASK |
+					EUR_CR_SOFT_RESET_TA_RESET_MASK  |
+					EUR_CR_SOFT_RESET_USE_RESET_MASK |
+					EUR_CR_SOFT_RESET_ISP_RESET_MASK |
+					EUR_CR_SOFT_RESET_TSP_RESET_MASK;
+
+#ifdef EUR_CR_SOFT_RESET_TWOD_RESET_MASK
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TWOD_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TE_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_MTE_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_MTE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_ISP2_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_ISP2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_PDS_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_PDS_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_PBE_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_PBE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_MADD_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_MADD_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_ITR_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_ITR_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TEX_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TEX_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_VDM_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_VDM_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK;
+#endif
+
+#if !defined(PDUMP)
+	PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+	if (bResetBIF)
+	{
+		ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_BIF_RESET_MASK;
+	}
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32SoftResetRegVal);
+	if (bPDump)
+	{
+		PDUMPREGWITHFLAGS(EUR_CR_SOFT_RESET, ui32SoftResetRegVal, ui32PDUMPFlags);
+	}
+}
+
+
+static IMG_VOID SGXResetSleep(PVRSRV_SGXDEV_INFO	*psDevInfo,
+							  IMG_UINT32			ui32PDUMPFlags,
+							  IMG_BOOL				bPDump)
+{
+#if !defined(PDUMP)
+	PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+
+	OSWaitus(1000 * 1000000 / psDevInfo->ui32CoreClockSpeed);
+	if (bPDump)
+	{
+		PDUMPIDLWITHFLAGS(30, ui32PDUMPFlags);
+#if defined(PDUMP)
+		PDumpRegRead(EUR_CR_SOFT_RESET, ui32PDUMPFlags);
+#endif
+	}
+
+
+
+}
+
+
+static IMG_VOID SGXResetInvalDC(PVRSRV_SGXDEV_INFO	*psDevInfo,
+							    IMG_UINT32			ui32PDUMPFlags,
+								IMG_BOOL			bPDump)
+{
+	IMG_UINT32 ui32RegVal;
+
+
+#if defined(EUR_CR_BIF_CTRL_INVAL)
+	ui32RegVal = EUR_CR_BIF_CTRL_INVAL_ALL_MASK;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, ui32RegVal);
+	if (bPDump)
+	{
+		PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL_INVAL, ui32RegVal, ui32PDUMPFlags);
+	}
+#else
+	ui32RegVal = EUR_CR_BIF_CTRL_INVALDC_MASK;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+	if (bPDump)
+	{
+		PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+	}
+	SGXResetSleep(psDevInfo, ui32PDUMPFlags, bPDump);
+
+	ui32RegVal = 0;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+	if (bPDump)
+	{
+		PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+	}
+#endif
+	SGXResetSleep(psDevInfo, ui32PDUMPFlags, bPDump);
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+	{
+
+
+
+		if (PollForValueKM((IMG_UINT32 *)((IMG_UINT8*)psDevInfo->pvRegsBaseKM + EUR_CR_BIF_MEM_REQ_STAT),
+							0,
+							EUR_CR_BIF_MEM_REQ_STAT_READS_MASK,
+							MAX_HW_TIME_US/WAIT_TRY_COUNT,
+							WAIT_TRY_COUNT) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"Wait for DC invalidate failed."));
+			PVR_DBG_BREAK;
+		}
+
+		if (bPDump)
+		{
+			PDUMPREGPOLWITHFLAGS(EUR_CR_BIF_MEM_REQ_STAT, 0, EUR_CR_BIF_MEM_REQ_STAT_READS_MASK, ui32PDUMPFlags);
+		}
+	}
+#endif
+}
+
+
+IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO	*psDevInfo,
+				  IMG_UINT32			 ui32PDUMPFlags)
+{
+	IMG_UINT32 ui32RegVal;
+#if defined(EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK)
+	const IMG_UINT32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK;
+#else
+	const IMG_UINT32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_MASK;
+#endif
+
+#ifndef PDUMP
+	PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+	psDevInfo->ui32NumResets++;
+
+	PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Start of SGX reset sequence\r\n");
+
+#if defined(FIX_HW_BRN_23944)
+
+	ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+	PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+	SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+	ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+	if (ui32RegVal & ui32BifFaultMask)
+	{
+
+		ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK | EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK;
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+		PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+		SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+		ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK;
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+		PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+		SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+	}
+#endif
+
+
+	SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_TRUE);
+
+	SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK);
+	PDUMPREGWITHFLAGS(EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK, ui32PDUMPFlags);
+#endif
+
+	ui32RegVal = 0;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+	PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+#if defined(SGX_FEATURE_MP)
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BIF_CTRL, ui32RegVal);
+	PDUMPREGWITHFLAGS(EUR_CR_MASTER_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+#endif
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK_SET, ui32RegVal);
+	PDUMPREGWITHFLAGS(EUR_CR_BIF_BANK_SET, ui32RegVal, ui32PDUMPFlags);
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
+	PDUMPREGWITHFLAGS(EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
+#endif
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
+	PDUMPREGWITHFLAGS(EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal, ui32PDUMPFlags);
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+	{
+		IMG_UINT32	ui32DirList, ui32DirListReg;
+
+		for (ui32DirList = 1;
+			 ui32DirList < SGX_FEATURE_BIF_NUM_DIRLISTS;
+			 ui32DirList++)
+		{
+			ui32DirListReg = EUR_CR_BIF_DIR_LIST_BASE1 + 4 * (ui32DirList - 1);
+			OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32DirListReg, ui32RegVal);
+			PDUMPREGWITHFLAGS(ui32DirListReg, ui32RegVal, ui32PDUMPFlags);
+		}
+	}
+#endif
+
+#if defined(EUR_CR_BIF_MEM_ARB_CONFIG)
+
+
+	ui32RegVal	= (12UL << EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_SHIFT) |
+				  (7UL << EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_SHIFT) |
+				  (12UL << EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_SHIFT);
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal);
+	PDUMPREGWITHFLAGS(EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal, ui32PDUMPFlags);
+#endif
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+#if defined(SGX_FEATURE_MP)
+	#if defined(SGX_BYPASS_SYSTEM_CACHE)
+		#error SGX_BYPASS_SYSTEM_CACHE not supported
+	#else
+		ui32RegVal = EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ0_MASK |
+						(0xC << EUR_CR_MASTER_SLC_CTRL_ARB_PAGE_SIZE_SHIFT);
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL, ui32RegVal);
+		PDUMPREG(EUR_CR_MASTER_SLC_CTRL, ui32RegVal);
+
+		ui32RegVal = EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_MASK;
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal);
+		PDUMPREG(EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal);
+	#endif
+#else
+	#if defined(SGX_BYPASS_SYSTEM_CACHE)
+
+		ui32RegVal = EUR_CR_MNE_CR_CTRL_BYPASS_ALL_MASK;
+	#else
+		#if defined(FIX_HW_BRN_26620)
+			ui32RegVal = 0;
+		#else
+
+			ui32RegVal = EUR_CR_MNE_CR_CTRL_BYP_CC_MASK;
+		#endif
+	#endif
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MNE_CR_CTRL, ui32RegVal);
+	PDUMPREG(EUR_CR_MNE_CR_CTRL, ui32RegVal);
+#endif
+#endif
+
+
+
+
+
+
+	ui32RegVal = psDevInfo->sBIFResetPDDevPAddr.uiAddr;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
+
+	SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+	SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE);
+	SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+	SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+
+	for (;;)
+	{
+		IMG_UINT32 ui32BifIntStat = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+		IMG_DEV_VIRTADDR sBifFault;
+		IMG_UINT32 ui32PDIndex, ui32PTIndex;
+
+		if ((ui32BifIntStat & ui32BifFaultMask) == 0)
+		{
+			break;
+		}
+
+
+
+
+		sBifFault.uiAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT);
+		PVR_DPF((PVR_DBG_WARNING, "SGXReset: Page fault 0x%x/0x%x", ui32BifIntStat, sBifFault.uiAddr));
+		ui32PDIndex = sBifFault.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+		ui32PTIndex = (sBifFault.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+
+		SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_FALSE);
+
+
+		psDevInfo->pui32BIFResetPD[ui32PDIndex] = (psDevInfo->sBIFResetPTDevPAddr.uiAddr
+												>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+												| SGX_MMU_PDE_PAGE_SIZE_4K
+												| SGX_MMU_PDE_VALID;
+		psDevInfo->pui32BIFResetPT[ui32PTIndex] = (psDevInfo->sBIFResetPageDevPAddr.uiAddr
+												>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+												| SGX_MMU_PTE_VALID;
+
+
+		ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32RegVal);
+		ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2, ui32RegVal);
+
+		SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+		SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_FALSE);
+		SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+		SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+		psDevInfo->pui32BIFResetPD[ui32PDIndex] = 0;
+		psDevInfo->pui32BIFResetPT[ui32PTIndex] = 0;
+	}
+
+
+
+
+	#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+
+	ui32RegVal = (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT);
+
+	#if defined(SGX_FEATURE_2D_HARDWARE)
+
+	ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_2D_SHIFT);
+	#endif
+
+	#if defined(FIX_HW_BRN_23410)
+
+	ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_TA_SHIFT);
+	#endif
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
+	PDUMPREGWITHFLAGS(EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
+	#endif
+
+	{
+		IMG_UINT32	ui32EDMDirListReg;
+
+
+		#if (SGX_BIF_DIR_LIST_INDEX_EDM == 0)
+		ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE0;
+		#else
+
+		ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE1 + 4 * (SGX_BIF_DIR_LIST_INDEX_EDM - 1);
+		#endif
+
+#if defined(FIX_HW_BRN_28011)
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT);
+		PDUMPPDREGWITHFLAGS(EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT, ui32PDUMPFlags, PDUMP_PD_UNIQUETAG);
+#endif
+
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32EDMDirListReg, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT);
+		PDUMPPDREGWITHFLAGS(ui32EDMDirListReg, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT, ui32PDUMPFlags, PDUMP_PD_UNIQUETAG);
+	}
+
+#ifdef SGX_FEATURE_2D_HARDWARE
+
+	#if ((SGX_2D_HEAP_BASE & ~EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK) != 0)
+		#error "SGXReset: SGX_2D_HEAP_BASE doesn't match EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK alignment"
+	#endif
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE);
+	PDUMPREGWITHFLAGS(EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE, ui32PDUMPFlags);
+#endif
+
+
+	SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+	PVR_DPF((PVR_DBG_MESSAGE,"Soft Reset of SGX"));
+	SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+
+	ui32RegVal = 0;
+#if defined(SGX_FEATURE_MP)
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SOFT_RESET, ui32RegVal);
+	PDUMPREGWITHFLAGS(EUR_CR_MASTER_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
+#endif
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32RegVal);
+	PDUMPREGWITHFLAGS(EUR_CR_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
+
+
+	SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+	PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "End of SGX reset sequence\r\n");
+}
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxtransfer.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxtransfer.c
new file mode 100644
index 0000000..9899f92
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxtransfer.c
@@ -0,0 +1,549 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if defined(TRANSFER_QUEUE)
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxinfo.h"
+#include "sysconfig.h"
+#include "regpaths.h"
+#include "pdump_km.h"
+#include "mmu.h"
+#include "pvr_bridge.h"
+#include "sgx_bridge_km.h"
+#include "sgxinfokm.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+
+int do_wait_vblank(void *display, int headline, int footline);
+
+IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK *psKick)
+{
+	PVRSRV_KERNEL_MEM_INFO  *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo;
+	SGXMKIF_COMMAND sCommand = {0};
+	SGXMKIF_TRANSFERCMD_SHARED *psSharedTransferCmd;
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+	PVRSRV_ERROR eError;
+
+
+	if (!CCB_OFFSET_IS_VALID(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: Invalid CCB offset"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+
+	psSharedTransferCmd =  CCB_DATA_FROM_OFFSET(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
+
+	if (psKick->hTASyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+		psSharedTransferCmd->ui32TASyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+		psSharedTransferCmd->ui32TASyncReadOpsPendingVal  = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+		psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+		psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+	}
+	else
+	{
+		psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+		psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr.uiAddr = 0;
+	}
+
+	if (psKick->h3DSyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+		psSharedTransferCmd->ui323DSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+		psSharedTransferCmd->ui323DSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+		psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+		psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+	}
+	else
+	{
+		psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+		psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr.uiAddr = 0;
+	}
+
+	if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+	{
+		if (psKick->ui32NumSrcSync > 0)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0];
+
+			psSharedTransferCmd->ui32SrcWriteOpPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+			psSharedTransferCmd->ui32SrcReadOpPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+			psSharedTransferCmd->sSrcWriteOpsCompleteDevAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+			psSharedTransferCmd->sSrcReadOpsCompleteDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+		}
+
+		if (psKick->ui32NumDstSync > 0)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+
+			psSharedTransferCmd->ui32DstWriteOpPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+			psSharedTransferCmd->ui32DstReadOpPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+			psSharedTransferCmd->sDstWriteOpsCompleteDevAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+			psSharedTransferCmd->sDstReadOpsCompleteDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+		}
+
+
+		if (psKick->ui32NumSrcSync > 0)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0];
+			psSyncInfo->psSyncData->ui32ReadOpsPending++;
+		}
+		if (psKick->ui32NumDstSync > 0)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+			psSyncInfo->psSyncData->ui32WriteOpsPending++;
+		}
+	}
+
+
+	if (psKick->ui32NumDstSync > 1 || psKick->ui32NumSrcSync  > 1)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+					"Transfer command doesn't support more than 1 sync object per src/dst\ndst: %d, src: %d",
+					psKick->ui32NumDstSync, psKick->ui32NumSrcSync));
+	}
+
+#if defined(PDUMP)
+	if (PDumpIsCaptureFrameKM()
+	|| ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+	{
+		PDUMPCOMMENT("Shared part of transfer command\r\n");
+		PDUMPMEM(psSharedTransferCmd,
+				psCCBMemInfo,
+				psKick->ui32CCBDumpWOff,
+				sizeof(SGXMKIF_TRANSFERCMD_SHARED),
+				psKick->ui32PDumpFlags,
+				MAKEUNIQUETAG(psCCBMemInfo));
+
+		if((psKick->ui32NumSrcSync > 0) && ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL))
+		{
+			psSyncInfo = psKick->ahSrcSyncInfo[0];
+
+			PDUMPCOMMENT("Hack src surface write op in transfer cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui32SrcWriteOpPendingVal),
+					sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+
+			PDUMPCOMMENT("Hack src surface read op in transfer cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui32SrcReadOpPendingVal),
+					sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+
+		}
+		if((psKick->ui32NumDstSync > 0) && ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL))
+		{
+			psSyncInfo = psKick->ahDstSyncInfo[0];
+
+			PDUMPCOMMENT("Hack dest surface write op in transfer cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui32DstWriteOpPendingVal),
+					sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+
+			PDUMPCOMMENT("Hack dest surface read op in transfer cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui32DstReadOpPendingVal),
+					sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+
+		}
+
+
+		if((psKick->ui32NumSrcSync > 0) && ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING)== 0UL))
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0];
+			psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+		}
+
+		if((psKick->ui32NumDstSync > 0) && ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL))
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+			psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+		}
+	}
+#endif
+
+	sCommand.ui32Data[1] = psKick->sHWTransferContextDevVAddr.uiAddr;
+
+	if (psKick->display)
+		do_wait_vblank(psKick->display, psKick->headline, psKick->footline);
+	eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_TRANSFER, &sCommand, KERNEL_ID, psKick->ui32PDumpFlags);
+
+	if (eError == PVRSRV_ERROR_RETRY)
+	{
+
+		if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+		{
+			if (psKick->ui32NumSrcSync > 0)
+			{
+				psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0];
+				psSyncInfo->psSyncData->ui32ReadOpsPending--;
+			}
+			if (psKick->ui32NumDstSync > 0)
+			{
+				psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+				psSyncInfo->psSyncData->ui32WriteOpsPending--;
+			}
+#if defined(PDUMP)
+			if (PDumpIsCaptureFrameKM()
+			|| ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+			{
+				if (psKick->ui32NumSrcSync > 0)
+				{
+					psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0];
+					psSyncInfo->psSyncData->ui32LastReadOpDumpVal--;
+				}
+				if (psKick->ui32NumDstSync > 0)
+				{
+					psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+					psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+				}
+			}
+#endif
+		}
+
+
+		if (psKick->hTASyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+			psSyncInfo->psSyncData->ui32WriteOpsPending--;
+		}
+
+
+		if (psKick->h3DSyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+			psSyncInfo->psSyncData->ui32WriteOpsPending--;
+		}
+	}
+
+	else if (PVRSRV_OK != eError)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: SGXScheduleCCBCommandKM failed."));
+		return eError;
+	}
+
+
+#if defined(NO_HARDWARE)
+	if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_NOSYNCUPDATE) == 0)
+	{
+		IMG_UINT32 i;
+
+
+		for(i = 0; i < psKick->ui32NumSrcSync; i++)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i];
+			psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+		}
+
+		for(i = 0; i < psKick->ui32NumDstSync; i++)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[i];
+			psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+		}
+
+		if (psKick->hTASyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+			psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+		}
+
+		if (psKick->h3DSyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+			psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+		}
+	}
+#endif
+
+	return eError;
+}
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK *psKick)
+
+{
+	PVRSRV_KERNEL_MEM_INFO  *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo;
+	SGXMKIF_COMMAND sCommand = {0};
+	SGXMKIF_2DCMD_SHARED *ps2DCmd;
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+	PVRSRV_ERROR eError;
+	IMG_UINT32 i;
+
+	if (!CCB_OFFSET_IS_VALID(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXSubmit2DKM: Invalid CCB offset"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+
+	ps2DCmd =  CCB_DATA_FROM_OFFSET(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
+
+	OSMemSet(ps2DCmd, 0, sizeof(*ps2DCmd));
+
+
+	if (psKick->hTASyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+		ps2DCmd->sTASyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+		ps2DCmd->sTASyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+		ps2DCmd->sTASyncData.sWriteOpsCompleteDevVAddr 	= psSyncInfo->sWriteOpsCompleteDevVAddr;
+		ps2DCmd->sTASyncData.sReadOpsCompleteDevVAddr 	= psSyncInfo->sReadOpsCompleteDevVAddr;
+	}
+
+
+	if (psKick->h3DSyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+		ps2DCmd->s3DSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+		ps2DCmd->s3DSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+		ps2DCmd->s3DSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+		ps2DCmd->s3DSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+	}
+
+
+	ps2DCmd->ui32NumSrcSync = psKick->ui32NumSrcSync;
+	for (i = 0; i < psKick->ui32NumSrcSync; i++)
+	{
+		psSyncInfo = psKick->ahSrcSyncInfo[i];
+
+		ps2DCmd->sSrcSyncData[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+		ps2DCmd->sSrcSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+		ps2DCmd->sSrcSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+		ps2DCmd->sSrcSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+	}
+
+	if (psKick->hDstSyncInfo != IMG_NULL)
+	{
+		psSyncInfo = psKick->hDstSyncInfo;
+
+		ps2DCmd->sDstSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+		ps2DCmd->sDstSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+		ps2DCmd->sDstSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+		ps2DCmd->sDstSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+	}
+
+
+	for (i = 0; i < psKick->ui32NumSrcSync; i++)
+	{
+		psSyncInfo = psKick->ahSrcSyncInfo[i];
+		psSyncInfo->psSyncData->ui32ReadOpsPending++;
+	}
+
+	if (psKick->hDstSyncInfo != IMG_NULL)
+	{
+		psSyncInfo = psKick->hDstSyncInfo;
+		psSyncInfo->psSyncData->ui32WriteOpsPending++;
+	}
+
+#if defined(PDUMP)
+	if (PDumpIsCaptureFrameKM()
+	|| ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+	{
+
+		PDUMPCOMMENT("Shared part of 2D command\r\n");
+		PDUMPMEM(ps2DCmd,
+				psCCBMemInfo,
+				psKick->ui32CCBDumpWOff,
+				sizeof(SGXMKIF_2DCMD_SHARED),
+				psKick->ui32PDumpFlags,
+				MAKEUNIQUETAG(psCCBMemInfo));
+
+		for (i = 0; i < psKick->ui32NumSrcSync; i++)
+		{
+			psSyncInfo = psKick->ahSrcSyncInfo[i];
+
+			PDUMPCOMMENT("Hack src surface write op in 2D cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32WriteOpsPendingVal),
+					sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+
+			PDUMPCOMMENT("Hack src surface read op in 2D cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32ReadOpsPendingVal),
+					sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+		}
+
+		if (psKick->hDstSyncInfo != IMG_NULL)
+		{
+			psSyncInfo = psKick->hDstSyncInfo;
+
+			PDUMPCOMMENT("Hack dest surface write op in 2D cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32WriteOpsPendingVal),
+					sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+
+			PDUMPCOMMENT("Hack dest surface read op in 2D cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32ReadOpsPendingVal),
+					sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+		}
+
+
+		for (i = 0; i < psKick->ui32NumSrcSync; i++)
+		{
+			psSyncInfo = psKick->ahSrcSyncInfo[i];
+			psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+		}
+
+		if (psKick->hDstSyncInfo != IMG_NULL)
+		{
+			psSyncInfo = psKick->hDstSyncInfo;
+			psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+		}
+	}
+#endif
+
+	sCommand.ui32Data[1] = psKick->sHW2DContextDevVAddr.uiAddr;
+
+	eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_2D, &sCommand, KERNEL_ID, psKick->ui32PDumpFlags);
+
+	if (eError == PVRSRV_ERROR_RETRY)
+	{
+
+
+#if defined(PDUMP)
+		if (PDumpIsCaptureFrameKM())
+		{
+			for (i = 0; i < psKick->ui32NumSrcSync; i++)
+			{
+				psSyncInfo = psKick->ahSrcSyncInfo[i];
+				psSyncInfo->psSyncData->ui32LastReadOpDumpVal--;
+			}
+
+			if (psKick->hDstSyncInfo != IMG_NULL)
+			{
+				psSyncInfo = psKick->hDstSyncInfo;
+				psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+			}
+		}
+#endif
+
+		for (i = 0; i < psKick->ui32NumSrcSync; i++)
+		{
+			psSyncInfo = psKick->ahSrcSyncInfo[i];
+			psSyncInfo->psSyncData->ui32ReadOpsPending--;
+		}
+
+		if (psKick->hDstSyncInfo != IMG_NULL)
+		{
+			psSyncInfo = psKick->hDstSyncInfo;
+			psSyncInfo->psSyncData->ui32WriteOpsPending--;
+		}
+
+
+		if (psKick->hTASyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+			psSyncInfo->psSyncData->ui32WriteOpsPending--;
+		}
+
+
+		if (psKick->h3DSyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+			psSyncInfo->psSyncData->ui32WriteOpsPending--;
+		}
+	}
+
+
+
+
+#if defined(NO_HARDWARE)
+
+	for(i = 0; i < psKick->ui32NumSrcSync; i++)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i];
+		psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+	}
+
+	psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hDstSyncInfo;
+	psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+	if (psKick->hTASyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+		psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+	}
+
+	if (psKick->h3DSyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+		psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+	}
+#endif
+
+	return eError;
+}
+#endif
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxutils.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxutils.c
new file mode 100644
index 0000000..8ffa3fa
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxutils.c
@@ -0,0 +1,1054 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgx_mkif_km.h"
+#include "sysconfig.h"
+#include "pdump_km.h"
+#include "mmu.h"
+#include "pvr_bridge_km.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+
+#ifdef __linux__
+#include <linux/tty.h>
+#else
+#include <stdio.h>
+#endif
+
+
+#if defined(SYS_CUSTOM_POWERDOWN)
+PVRSRV_ERROR SysPowerDownMISR(PVRSRV_DEVICE_NODE	* psDeviceNode, IMG_UINT32 ui32CallerID);
+#endif
+
+
+
+IMG_VOID SGXPostActivePowerEvent(PVRSRV_DEVICE_NODE	* psDeviceNode,
+                                 IMG_UINT32           ui32CallerID)
+{
+	PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+	SGXMKIF_HOST_CTL	*psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+
+	psSGXHostCtl->ui32NumActivePowerEvents++;
+
+	if ((psSGXHostCtl->ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE) != 0)
+	{
+
+
+
+		if (ui32CallerID == ISR_ID)
+		{
+			psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+		}
+		else
+		{
+			SGXScheduleProcessQueuesKM(psDeviceNode);
+		}
+	}
+}
+
+
+IMG_VOID SGXTestActivePowerEvent (PVRSRV_DEVICE_NODE	*psDeviceNode,
+								  IMG_UINT32			ui32CallerID)
+{
+	PVRSRV_ERROR		eError = PVRSRV_OK;
+	PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+	SGXMKIF_HOST_CTL	*psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+	if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0) &&
+		((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0))
+	{
+
+		psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
+
+
+		PDUMPSUSPEND();
+
+#if defined(SYS_CUSTOM_POWERDOWN)
+
+
+
+		eError = SysPowerDownMISR(psDeviceNode, ui32CallerID);
+#else
+		eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+											 PVRSRV_DEV_POWER_STATE_OFF,
+											 ui32CallerID, IMG_FALSE);
+		if (eError == PVRSRV_OK)
+		{
+			SGXPostActivePowerEvent(psDeviceNode, ui32CallerID);
+		}
+#endif
+		if (eError == PVRSRV_ERROR_RETRY)
+		{
+
+
+			psSGXHostCtl->ui32InterruptClearFlags &= ~PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
+			eError = PVRSRV_OK;
+		}
+
+
+		PDUMPRESUME();
+	}
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXTestActivePowerEvent error:%lu", eError));
+	}
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGXAcquireKernelCCBSlot)
+#endif
+static INLINE SGXMKIF_COMMAND * SGXAcquireKernelCCBSlot(PVRSRV_SGX_CCB_INFO *psCCB)
+{
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		if(((*psCCB->pui32WriteOffset + 1) & 255) != *psCCB->pui32ReadOffset)
+		{
+			return &psCCB->psCommands[*psCCB->pui32WriteOffset];
+		}
+
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+
+	return IMG_NULL;
+}
+
+PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_SGXDEV_INFO 	*psDevInfo,
+								   SGXMKIF_CMD_TYPE		eCmdType,
+								   SGXMKIF_COMMAND		*psCommandData,
+								   IMG_UINT32			ui32CallerID,
+								   IMG_UINT32			ui32PDumpFlags)
+{
+	PVRSRV_SGX_CCB_INFO *psKernelCCB;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+	SGXMKIF_COMMAND *psSGXCommand;
+#if defined(PDUMP)
+	IMG_VOID *pvDumpCommand;
+	IMG_BOOL bPDumpIsSuspended = PDumpIsSuspended();
+#else
+	PVR_UNREFERENCED_PARAMETER(ui32CallerID);
+	PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+#endif
+
+#if defined(FIX_HW_BRN_28889)
+
+
+
+
+	if ( (eCmdType != SGXMKIF_CMD_PROCESS_QUEUES) &&
+		 ((psDevInfo->ui32CacheControl & SGXMKIF_CC_INVAL_DATA) != 0) &&
+		 ((psDevInfo->ui32CacheControl & (SGXMKIF_CC_INVAL_BIF_PT | SGXMKIF_CC_INVAL_BIF_PD)) != 0))
+	{
+	#if defined(PDUMP)
+		PVRSRV_KERNEL_MEM_INFO	*psSGXHostCtlMemInfo = psDevInfo->psKernelSGXHostCtlMemInfo;
+	#endif
+		SGXMKIF_HOST_CTL	*psSGXHostCtl = psDevInfo->psSGXHostCtl;
+		SGXMKIF_COMMAND		sCacheCommand = {0};
+
+		eError = SGXScheduleCCBCommand(psDevInfo,
+									   SGXMKIF_CMD_PROCESS_QUEUES,
+									   &sCacheCommand,
+									   ui32CallerID,
+									   ui32PDumpFlags);
+		if (eError != PVRSRV_OK)
+		{
+			goto Exit;
+		}
+
+
+		#if !defined(NO_HARDWARE)
+		if(PollForValueKM(&psSGXHostCtl->ui32InvalStatus,
+						  PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+						  PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+						  2 * MAX_HW_TIME_US/WAIT_TRY_COUNT,
+						  WAIT_TRY_COUNT) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommand: Wait for uKernel to Invalidate BIF cache failed"));
+			PVR_DBG_BREAK;
+		}
+		#endif
+
+		psSGXHostCtl->ui32InvalStatus &= ~(PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE);
+
+		#if defined(PDUMP)
+		if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE))
+		{
+
+			PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for BIF cache invalidate request to complete");
+			PDUMPMEMPOL(psSGXHostCtlMemInfo,
+						offsetof(SGXMKIF_HOST_CTL, ui32InvalStatus),
+						PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+						PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+						PDUMP_POLL_OPERATOR_EQUAL,
+						0,
+						MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+			PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+		}
+		#endif
+	}
+#endif
+
+	psKernelCCB = psDevInfo->psKernelCCBInfo;
+
+	psSGXCommand = SGXAcquireKernelCCBSlot(psKernelCCB);
+
+
+	if(!psSGXCommand)
+	{
+		eError = PVRSRV_ERROR_TIMEOUT;
+		goto Exit;
+	}
+
+
+	psCommandData->ui32CacheControl = psDevInfo->ui32CacheControl;
+
+#if defined(PDUMP)
+
+	psDevInfo->sPDContext.ui32CacheControl |= psDevInfo->ui32CacheControl;
+#endif
+
+
+	psDevInfo->ui32CacheControl = 0;
+
+
+	*psSGXCommand = *psCommandData;
+
+	if (eCmdType >= SGXMKIF_CMD_MAX)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM: Unknown command type: %d", eCmdType)) ;
+		eError = PVRSRV_ERROR_GENERIC;
+		goto Exit;
+	}
+
+#if defined(SUPPORT_CPU_CACHED_BUFFERS)
+	{
+		SYS_DATA *psSysData;
+
+		SysAcquireData(&psSysData);
+
+		if (psSysData->bFlushAll)
+		{
+			OSFlushCPUCacheKM();
+
+			psSysData->bFlushAll = IMG_FALSE;
+		}
+	}
+#endif
+
+	psSGXCommand->ui32ServiceAddress = psDevInfo->aui32HostKickAddr[eCmdType];
+
+#if defined(PDUMP)
+	if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE))
+	{
+
+		PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for space in the Kernel CCB\r\n");
+		PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
+					offsetof(PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
+					(psKernelCCB->ui32CCBDumpWOff + 1) & 0xff,
+					0xff,
+					PDUMP_POLL_OPERATOR_NOTEQUAL,
+					ui32PDumpFlags,
+					MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+
+		PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB command\r\n");
+		pvDumpCommand = (IMG_VOID *)((IMG_UINT8 *)psKernelCCB->psCCBMemInfo->pvLinAddrKM + (*psKernelCCB->pui32WriteOffset * sizeof(SGXMKIF_COMMAND)));
+
+		PDUMPMEM(pvDumpCommand,
+					psKernelCCB->psCCBMemInfo,
+					psKernelCCB->ui32CCBDumpWOff * sizeof(SGXMKIF_COMMAND),
+					sizeof(SGXMKIF_COMMAND),
+					ui32PDumpFlags,
+					MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
+
+
+		PDUMPMEM(&psDevInfo->sPDContext.ui32CacheControl,
+					psKernelCCB->psCCBMemInfo,
+					psKernelCCB->ui32CCBDumpWOff * sizeof(SGXMKIF_COMMAND) +
+					offsetof(SGXMKIF_COMMAND, ui32CacheControl),
+					sizeof(IMG_UINT32),
+					ui32PDumpFlags,
+					MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
+
+		if (PDumpIsCaptureFrameKM()
+		|| ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+		{
+
+			psDevInfo->sPDContext.ui32CacheControl = 0;
+		}
+	}
+#endif
+
+#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+
+	eError = PollForValueKM (psKernelCCB->pui32ReadOffset,
+								*psKernelCCB->pui32WriteOffset,
+								0xFF,
+								MAX_HW_TIME_US/WAIT_TRY_COUNT,
+								WAIT_TRY_COUNT);
+	if (eError != PVRSRV_OK)
+	{
+		eError = PVRSRV_ERROR_TIMEOUT;
+		goto Exit;
+	}
+#endif
+
+
+
+	*psKernelCCB->pui32WriteOffset = (*psKernelCCB->pui32WriteOffset + 1) & 255;
+
+#if defined(PDUMP)
+	if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE))
+	{
+	#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+		PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for previous Kernel CCB CMD to be read\r\n");
+		PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
+					offsetof(PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
+					(psKernelCCB->ui32CCBDumpWOff),
+					0xFF,
+					PDUMP_POLL_OPERATOR_EQUAL,
+					ui32PDumpFlags,
+					MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+	#endif
+
+		if (PDumpIsCaptureFrameKM()
+		|| ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+		{
+			psKernelCCB->ui32CCBDumpWOff = (psKernelCCB->ui32CCBDumpWOff + 1) & 0xFF;
+			psDevInfo->ui32KernelCCBEventKickerDumpVal = (psDevInfo->ui32KernelCCBEventKickerDumpVal + 1) & 0xFF;
+		}
+
+		PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB write offset\r\n");
+		PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff,
+				 psKernelCCB->psCCBCtlMemInfo,
+				 offsetof(PVRSRV_SGX_CCB_CTL, ui32WriteOffset),
+				 sizeof(IMG_UINT32),
+				 ui32PDumpFlags,
+				 MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+		PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB event kicker\r\n");
+		PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+				 psDevInfo->psKernelCCBEventKickerMemInfo,
+				 0,
+				 sizeof(IMG_UINT32),
+				 ui32PDumpFlags,
+				 MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+		PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kick the SGX microkernel\r\n");
+	#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+		PDUMPREGWITHFLAGS(SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0), EUR_CR_EVENT_KICK2_NOW_MASK, ui32PDumpFlags);
+	#else
+		PDUMPREGWITHFLAGS(SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), EUR_CR_EVENT_KICK_NOW_MASK, ui32PDumpFlags);
+	#endif
+	}
+#endif
+
+	*psDevInfo->pui32KernelCCBEventKicker = (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+				SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0),
+				EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+				SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
+				EUR_CR_EVENT_KICK_NOW_MASK);
+#endif
+
+#if defined(NO_HARDWARE)
+
+	*psKernelCCB->pui32ReadOffset = (*psKernelCCB->pui32ReadOffset + 1) & 255;
+#endif
+
+Exit:
+	return eError;
+}
+
+
+PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE		*psDeviceNode,
+									 SGXMKIF_CMD_TYPE		eCmdType,
+									 SGXMKIF_COMMAND		*psCommandData,
+									 IMG_UINT32				ui32CallerID,
+									 IMG_UINT32				ui32PDumpFlags)
+{
+	PVRSRV_ERROR		eError;
+	PVRSRV_SGXDEV_INFO 	*psDevInfo = psDeviceNode->pvDevice;
+
+
+	PDUMPSUSPEND();
+
+
+	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+										 PVRSRV_DEV_POWER_STATE_ON,
+										 ui32CallerID,
+										 IMG_TRUE);
+
+	PDUMPRESUME();
+
+	if (eError == PVRSRV_OK)
+	{
+		psDeviceNode->bReProcessDeviceCommandComplete = IMG_FALSE;
+	}
+	else
+	{
+		if (eError == PVRSRV_ERROR_RETRY)
+		{
+			if (ui32CallerID == ISR_ID)
+			{
+
+
+
+				psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+				eError = PVRSRV_OK;
+			}
+			else
+			{
+
+
+			}
+		}
+		else
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM failed to acquire lock - "
+					 "ui32CallerID:%ld eError:%lu", ui32CallerID, eError));
+		}
+
+		return eError;
+	}
+
+	eError = SGXScheduleCCBCommand(psDevInfo, eCmdType, psCommandData, ui32CallerID, ui32PDumpFlags);
+
+	PVRSRVPowerUnlock(ui32CallerID);
+
+	if (ui32CallerID != ISR_ID)
+	{
+
+
+
+		SGXTestActivePowerEvent(psDeviceNode, ui32CallerID);
+	}
+
+	return eError;
+}
+
+
+#define print_error(function, variable)\
+{\
+	printk(KERN_ERR "ERROR!\nERROR!\nERROR!\n");\
+	printk(KERN_ERR "ERROR: %s() about to dereference a NULL pointer!\n", function);\
+	printk(KERN_ERR "  %s is NULL\n", variable);\
+	printk(KERN_ERR "  The client-side program needs to call SrvInit()\n");\
+	printk(KERN_ERR "  Working-around error by exiting the function early\n");\
+}
+
+
+PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	/* Note: If the client-side code doesn't call SrvInit(), the normal
+	 * implementation of this function will chase a NULL pointer.  The
+	 * workaround is to use an extra set of curly braces, and then to check the
+	 * pointers normally used during the variable initialization code.  if a
+	 * problem is found, exit early and provide a helpful error message in the
+	 * kernel log file.
+	 */
+	if (NULL == psDeviceNode) {
+		print_error(__FUNCTION__, "psDeviceNode");
+		return PVRSRV_OK;
+	} else {
+		PVRSRV_SGXDEV_INFO 	*psDevInfo = psDeviceNode->pvDevice;
+		if (NULL == psDevInfo) {
+			print_error(__FUNCTION__, "psDevInfo");
+			return PVRSRV_OK;
+		}
+		if (NULL == psDevInfo->psKernelSGXHostCtlMemInfo) {
+			print_error(__FUNCTION__, "psDevInfo->psKernelSGXHostCtlMemInfo");
+			return PVRSRV_OK;
+		}
+		if (NULL == psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM) {
+			print_error(__FUNCTION__,
+				"psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM");
+			return PVRSRV_OK;
+		}
+	}
+	/* Below starts the extra set of curly-braces, and the original function: */
+{
+	PVRSRV_ERROR 		eError;
+	PVRSRV_SGXDEV_INFO 	*psDevInfo = psDeviceNode->pvDevice;
+	SGXMKIF_HOST_CTL	*psHostCtl = psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
+	IMG_UINT32		ui32PowerStatus;
+	SGXMKIF_COMMAND		sCommand = {0};
+
+	ui32PowerStatus = psHostCtl->ui32PowerStatus;
+	if ((ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0)
+	{
+
+		return PVRSRV_OK;
+	}
+
+	eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_PROCESS_QUEUES, &sCommand, ISR_ID, 0);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXScheduleProcessQueuesKM failed to schedule CCB command: %lu", eError));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	return PVRSRV_OK;
+}
+}
+
+
+IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	return PVRSRVIsDevicePowered(psDeviceNode->sDevId.ui32DeviceIndex);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
+									SGX_INTERNAL_DEVINFO *psSGXInternalDevInfo)
+{
+	PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+	psSGXInternalDevInfo->ui32Flags = psDevInfo->ui32Flags;
+	psSGXInternalDevInfo->bForcePTOff = (IMG_BOOL)psDevInfo->bForcePTOff;
+
+
+	psSGXInternalDevInfo->hHostCtlKernelMemInfoHandle =
+		(IMG_HANDLE)psDevInfo->psKernelSGXHostCtlMemInfo;
+
+	return PVRSRV_OK;
+}
+
+
+IMG_VOID SGXCleanupRequest(PVRSRV_DEVICE_NODE	*psDeviceNode,
+						   IMG_DEV_VIRTADDR		*psHWDataDevVAddr,
+						   IMG_UINT32			ui32CleanupType)
+{
+	/* Note: If the client-side code doesn't call SrvInit(), the normal
+	 * implementation of this function will chase a NULL pointer.  The
+	 * workaround is to use an extra set of curly braces, and then to check the
+	 * pointers normally used during the variable initialization code.  if a
+	 * problem is found, exit early and provide a helpful error message in the
+	 * kernel log file.
+	 */
+	if (NULL == psDeviceNode) {
+		print_error(__FUNCTION__, "psDeviceNode");
+		return;
+	} else {
+		PVRSRV_SGXDEV_INFO 	*psSGXDevInfo = psDeviceNode->pvDevice;
+		if (NULL == psSGXDevInfo) {
+			print_error(__FUNCTION__, "psSGXDevInfo");
+			return;
+		}
+		if (NULL == psSGXDevInfo->psKernelSGXHostCtlMemInfo) {
+			print_error(__FUNCTION__,"psSGXDevInfo->psKernelSGXHostCtlMemInfo");
+			return;
+		} else {
+			PVRSRV_KERNEL_MEM_INFO	*psSGXHostCtlMemInfo =
+				psSGXDevInfo->psKernelSGXHostCtlMemInfo;
+			if (NULL == psSGXHostCtlMemInfo->pvLinAddrKM) {
+				print_error(__FUNCTION__, "psSGXHostCtlMemInfo->pvLinAddrKM");
+				return;
+			}
+		}
+	}
+	/* Below starts the extra set of curly-braces, and the original function: */
+{
+	PVRSRV_ERROR			eError;
+	PVRSRV_SGXDEV_INFO		*psSGXDevInfo = psDeviceNode->pvDevice;
+	PVRSRV_KERNEL_MEM_INFO	*psSGXHostCtlMemInfo = psSGXDevInfo->psKernelSGXHostCtlMemInfo;
+	SGXMKIF_HOST_CTL		*psSGXHostCtl = psSGXHostCtlMemInfo->pvLinAddrKM;
+
+	if ((psSGXHostCtl->ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0)
+	{
+
+	}
+	else
+	{
+		SGXMKIF_COMMAND		sCommand = {0};
+
+		PDUMPCOMMENTWITHFLAGS(0, "Request ukernel resouce clean-up");
+		sCommand.ui32Data[0] = ui32CleanupType;
+		sCommand.ui32Data[1] = (psHWDataDevVAddr == IMG_NULL) ? 0 : psHWDataDevVAddr->uiAddr;
+
+		eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_CLEANUP, &sCommand, KERNEL_ID, 0);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Failed to submit clean-up command"));
+			PVR_DBG_BREAK;
+		}
+
+
+		#if !defined(NO_HARDWARE)
+		if(PollForValueKM(&psSGXHostCtl->ui32CleanupStatus,
+						  PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+						  PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+						  MAX_HW_TIME_US/WAIT_TRY_COUNT,
+						  WAIT_TRY_COUNT) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Wait for uKernel to clean up failed"));
+			PVR_DBG_BREAK;
+		}
+		#endif
+
+		#if defined(PDUMP)
+
+		PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for clean-up request to complete");
+		PDUMPMEMPOL(psSGXHostCtlMemInfo,
+					offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus),
+					PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+					PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+					PDUMP_POLL_OPERATOR_EQUAL,
+					0,
+					MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+		#endif
+
+		psSGXHostCtl->ui32CleanupStatus &= ~(PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE);
+		PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+
+	#if defined(SGX_FEATURE_SYSTEM_CACHE)
+		psSGXDevInfo->ui32CacheControl |= (SGXMKIF_CC_INVAL_BIF_SL | SGXMKIF_CC_INVAL_DATA);
+	#else
+		psSGXDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_DATA;
+	#endif
+	}
+}
+}
+
+
+typedef struct _SGX_HW_RENDER_CONTEXT_CLEANUP_
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	IMG_DEV_VIRTADDR sHWRenderContextDevVAddr;
+	IMG_HANDLE hBlockAlloc;
+	PRESMAN_ITEM psResItem;
+} SGX_HW_RENDER_CONTEXT_CLEANUP;
+
+
+static PVRSRV_ERROR SGXCleanupHWRenderContextCallback(IMG_PVOID		pvParam,
+													  IMG_UINT32	ui32Param)
+{
+	SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup = pvParam;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+	SGXCleanupRequest(psCleanup->psDeviceNode,
+					  &psCleanup->sHWRenderContextDevVAddr,
+					  PVRSRV_CLEANUPCMD_RC);
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+			  sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+			  psCleanup,
+			  psCleanup->hBlockAlloc);
+
+
+	return PVRSRV_OK;
+}
+
+typedef struct _SGX_HW_TRANSFER_CONTEXT_CLEANUP_
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
+	IMG_HANDLE hBlockAlloc;
+	PRESMAN_ITEM psResItem;
+} SGX_HW_TRANSFER_CONTEXT_CLEANUP;
+
+
+static PVRSRV_ERROR SGXCleanupHWTransferContextCallback(IMG_PVOID	pvParam,
+														IMG_UINT32	ui32Param)
+{
+	SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup = (SGX_HW_TRANSFER_CONTEXT_CLEANUP *)pvParam;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+	SGXCleanupRequest(psCleanup->psDeviceNode,
+					  &psCleanup->sHWTransferContextDevVAddr,
+					  PVRSRV_CLEANUPCMD_TC);
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+			  sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+			  psCleanup,
+			  psCleanup->hBlockAlloc);
+
+
+	return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE				psDeviceNode,
+										IMG_DEV_VIRTADDR		*psHWRenderContextDevVAddr,
+										PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hBlockAlloc;
+	SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
+	PRESMAN_ITEM psResItem;
+
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+						(IMG_VOID **)&psCleanup,
+						&hBlockAlloc,
+						"SGX Hardware Render Context Cleanup");
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: Couldn't allocate memory for SGX_HW_RENDER_CONTEXT_CLEANUP structure"));
+		return IMG_NULL;
+	}
+
+	psCleanup->hBlockAlloc = hBlockAlloc;
+	psCleanup->psDeviceNode = psDeviceNode;
+	psCleanup->sHWRenderContextDevVAddr = *psHWRenderContextDevVAddr;
+
+	psResItem = ResManRegisterRes(psPerProc->hResManContext,
+								  RESMAN_TYPE_HW_RENDER_CONTEXT,
+								  (IMG_VOID *)psCleanup,
+								  0,
+								  &SGXCleanupHWRenderContextCallback);
+
+	if (psResItem == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: ResManRegisterRes failed"));
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+				  psCleanup,
+				  psCleanup->hBlockAlloc);
+
+
+		return IMG_NULL;
+	}
+
+	psCleanup->psResItem = psResItem;
+
+	return (IMG_HANDLE)psCleanup;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHWRenderContextKM(IMG_HANDLE hHWRenderContext)
+{
+	PVRSRV_ERROR eError;
+	SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
+
+	PVR_ASSERT(hHWRenderContext != IMG_NULL);
+
+	psCleanup = (SGX_HW_RENDER_CONTEXT_CLEANUP *)hHWRenderContext;
+
+	if (psCleanup == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXUnregisterHWRenderContextKM: invalid parameter"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	eError = ResManFreeResByPtr(psCleanup->psResItem);
+
+	return eError;
+}
+
+
+IMG_EXPORT
+IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE				psDeviceNode,
+										  IMG_DEV_VIRTADDR			*psHWTransferContextDevVAddr,
+										  PVRSRV_PER_PROCESS_DATA	*psPerProc)
+{
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hBlockAlloc;
+	SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
+	PRESMAN_ITEM psResItem;
+
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+						(IMG_VOID **)&psCleanup,
+						&hBlockAlloc,
+						"SGX Hardware Transfer Context Cleanup");
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: Couldn't allocate memory for SGX_HW_TRANSFER_CONTEXT_CLEANUP structure"));
+		return IMG_NULL;
+	}
+
+	psCleanup->hBlockAlloc = hBlockAlloc;
+	psCleanup->psDeviceNode = psDeviceNode;
+	psCleanup->sHWTransferContextDevVAddr = *psHWTransferContextDevVAddr;
+
+	psResItem = ResManRegisterRes(psPerProc->hResManContext,
+								  RESMAN_TYPE_HW_TRANSFER_CONTEXT,
+								  psCleanup,
+								  0,
+								  &SGXCleanupHWTransferContextCallback);
+
+	if (psResItem == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: ResManRegisterRes failed"));
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+				  psCleanup,
+				  psCleanup->hBlockAlloc);
+
+
+		return IMG_NULL;
+	}
+
+	psCleanup->psResItem = psResItem;
+
+	return (IMG_HANDLE)psCleanup;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHWTransferContextKM(IMG_HANDLE hHWTransferContext)
+{
+	PVRSRV_ERROR eError;
+	SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
+
+	PVR_ASSERT(hHWTransferContext != IMG_NULL);
+
+	psCleanup = (SGX_HW_TRANSFER_CONTEXT_CLEANUP *)hHWTransferContext;
+
+	if (psCleanup == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXUnregisterHWTransferContextKM: invalid parameter"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	eError = ResManFreeResByPtr(psCleanup->psResItem);
+
+	return eError;
+}
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _SGX_HW_2D_CONTEXT_CLEANUP_
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	IMG_DEV_VIRTADDR sHW2DContextDevVAddr;
+	IMG_HANDLE hBlockAlloc;
+	PRESMAN_ITEM psResItem;
+} SGX_HW_2D_CONTEXT_CLEANUP;
+
+static PVRSRV_ERROR SGXCleanupHW2DContextCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+	SGX_HW_2D_CONTEXT_CLEANUP *psCleanup = (SGX_HW_2D_CONTEXT_CLEANUP *)pvParam;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+	SGXCleanupRequest(psCleanup->psDeviceNode,
+					  &psCleanup->sHW2DContextDevVAddr,
+					  PVRSRV_CLEANUPCMD_2DC);
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+			  sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+			  psCleanup,
+			  psCleanup->hBlockAlloc);
+
+
+	return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE				psDeviceNode,
+									IMG_DEV_VIRTADDR		*psHW2DContextDevVAddr,
+									PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hBlockAlloc;
+	SGX_HW_2D_CONTEXT_CLEANUP *psCleanup;
+	PRESMAN_ITEM psResItem;
+
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+						(IMG_VOID **)&psCleanup,
+						&hBlockAlloc,
+						"SGX Hardware 2D Context Cleanup");
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: Couldn't allocate memory for SGX_HW_2D_CONTEXT_CLEANUP structure"));
+		return IMG_NULL;
+	}
+
+	psCleanup->hBlockAlloc = hBlockAlloc;
+	psCleanup->psDeviceNode = psDeviceNode;
+	psCleanup->sHW2DContextDevVAddr = *psHW2DContextDevVAddr;
+
+	psResItem = ResManRegisterRes(psPerProc->hResManContext,
+								  RESMAN_TYPE_HW_2D_CONTEXT,
+								  psCleanup,
+								  0,
+								  &SGXCleanupHW2DContextCallback);
+
+	if (psResItem == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: ResManRegisterRes failed"));
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+				  psCleanup,
+				  psCleanup->hBlockAlloc);
+
+
+		return IMG_NULL;
+	}
+
+	psCleanup->psResItem = psResItem;
+
+	return (IMG_HANDLE)psCleanup;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHW2DContextKM(IMG_HANDLE hHW2DContext)
+{
+	PVRSRV_ERROR eError;
+	SGX_HW_2D_CONTEXT_CLEANUP *psCleanup;
+
+	PVR_ASSERT(hHW2DContext != IMG_NULL);
+
+	if (hHW2DContext == IMG_NULL)
+	{
+		return (PVRSRV_ERROR_INVALID_PARAMS);
+	}
+
+	psCleanup = (SGX_HW_2D_CONTEXT_CLEANUP *)hHW2DContext;
+
+	eError = ResManFreeResByPtr(psCleanup->psResItem);
+
+	return eError;
+}
+#endif
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGX2DQuerySyncOpsComplete)
+#endif
+static INLINE
+IMG_BOOL SGX2DQuerySyncOpsComplete(PVRSRV_KERNEL_SYNC_INFO	*psSyncInfo,
+								   IMG_UINT32				ui32ReadOpsPending,
+								   IMG_UINT32				ui32WriteOpsPending)
+{
+	PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+	return (IMG_BOOL)(
+					  (psSyncData->ui32ReadOpsComplete >= ui32ReadOpsPending) &&
+					  (psSyncData->ui32WriteOpsComplete >= ui32WriteOpsPending)
+					 );
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO	*psDevInfo,
+									   PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+									   IMG_BOOL bWaitForComplete)
+{
+	IMG_UINT32	ui32ReadOpsPending, ui32WriteOpsPending;
+
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+	PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Start"));
+
+	ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending;
+	ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+	if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending))
+	{
+
+		PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Blits complete."));
+		return PVRSRV_OK;
+	}
+
+
+	if (!bWaitForComplete)
+	{
+
+		PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Ops pending."));
+		return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+	}
+
+
+	PVR_DPF((PVR_DBG_MESSAGE, "SGX2DQueryBlitsCompleteKM: Ops pending. Start polling."));
+
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+
+		if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending))
+		{
+
+			PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Wait over.  Blits complete."));
+			return PVRSRV_OK;
+		}
+
+		OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+
+	PVR_DPF((PVR_DBG_ERROR,"SGX2DQueryBlitsCompleteKM: Timed out. Ops pending."));
+
+#if defined(DEBUG)
+	{
+		PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+		PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Syncinfo: %p, Syncdata: %p", psSyncInfo, psSyncData));
+
+		PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Read ops complete: %d, Read ops pending: %d", psSyncData->ui32ReadOpsComplete, psSyncData->ui32ReadOpsPending));
+		PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Write ops complete: %d, Write ops pending: %d", psSyncData->ui32WriteOpsComplete, psSyncData->ui32WriteOpsPending));
+
+	}
+#endif
+
+	return PVRSRV_ERROR_TIMEOUT;
+}
+
+
+IMG_EXPORT
+IMG_VOID SGXFlushHWRenderTargetKM(IMG_HANDLE psDeviceNode, IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr)
+{
+	PVR_ASSERT(sHWRTDataSetDevVAddr.uiAddr != IMG_NULL);
+
+	SGXCleanupRequest(psDeviceNode,
+					  &sHWRTDataSetDevVAddr,
+					  PVRSRV_CLEANUPCMD_RT);
+}
+
+
+IMG_UINT32 SGXConvertTimeStamp(PVRSRV_SGXDEV_INFO	*psDevInfo,
+							   IMG_UINT32			ui32TimeWraps,
+							   IMG_UINT32			ui32Time)
+{
+#if defined(EUR_CR_TIMER)
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+	PVR_UNREFERENCED_PARAMETER(ui32TimeWraps);
+	return ui32Time;
+#else
+	IMG_UINT64	ui64Clocks;
+	IMG_UINT32	ui32Clocksx16;
+
+	ui64Clocks = ((IMG_UINT64)ui32TimeWraps * psDevInfo->ui32uKernelTimerClock) +
+					(psDevInfo->ui32uKernelTimerClock - (ui32Time & EUR_CR_EVENT_TIMER_VALUE_MASK));
+	ui32Clocksx16 = (IMG_UINT32)(ui64Clocks / 16);
+
+	return ui32Clocksx16;
+#endif
+}
+
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxutils.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxutils.h
new file mode 100644
index 0000000..ead8d56
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/devices/sgx/sgxutils.h
@@ -0,0 +1,95 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "perproc.h"
+#include "sgxinfokm.h"
+
+#define CCB_OFFSET_IS_VALID(type, psCCBMemInfo, psCCBKick, offset) \
+	((sizeof(type) <= (psCCBMemInfo)->ui32AllocSize) && \
+	((psCCBKick)->offset <= (psCCBMemInfo)->ui32AllocSize - sizeof(type)))
+
+#define	CCB_DATA_FROM_OFFSET(type, psCCBMemInfo, psCCBKick, offset) \
+	((type *)(((IMG_CHAR *)(psCCBMemInfo)->pvLinAddrKM) + \
+		(psCCBKick)->offset))
+
+
+IMG_IMPORT
+IMG_VOID SGXTestActivePowerEvent(PVRSRV_DEVICE_NODE	*psDeviceNode,
+								 IMG_UINT32			ui32CallerID);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_SGXDEV_INFO 	*psDevInfo,
+								   SGXMKIF_CMD_TYPE		eCommandType,
+								   SGXMKIF_COMMAND		*psCommandData,
+								   IMG_UINT32			ui32CallerID,
+								   IMG_UINT32			ui32PDumpFlags);
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE		*psDeviceNode,
+									 SGXMKIF_CMD_TYPE		eCommandType,
+									 SGXMKIF_COMMAND		*psCommandData,
+									 IMG_UINT32				ui32CallerID,
+									 IMG_UINT32				ui32PDumpFlags);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_IMPORT
+IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE				psDeviceNode,
+										IMG_DEV_VIRTADDR		*psHWRenderContextDevVAddr,
+										PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE				psDeviceNode,
+										  IMG_DEV_VIRTADDR			*psHWTransferContextDevVAddr,
+										  PVRSRV_PER_PROCESS_DATA	*psPerProc);
+
+IMG_IMPORT
+IMG_VOID SGXFlushHWRenderTargetKM(IMG_HANDLE psSGXDevInfo, IMG_DEV_VIRTADDR psHWRTDataSetDevVAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHWRenderContextKM(IMG_HANDLE hHWRenderContext);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHWTransferContextKM(IMG_HANDLE hHWTransferContext);
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE				psDeviceNode,
+									IMG_DEV_VIRTADDR		*psHW2DContextDevVAddr,
+									PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHW2DContextKM(IMG_HANDLE hHW2DContext);
+#endif
+
+IMG_UINT32 SGXConvertTimeStamp(PVRSRV_SGXDEV_INFO	*psDevInfo,
+							   IMG_UINT32			ui32TimeWraps,
+							   IMG_UINT32			ui32Time);
+
+IMG_VOID SGXCleanupRequest(PVRSRV_DEVICE_NODE	*psDeviceNode,
+							IMG_DEV_VIRTADDR	*psHWDataDevVAddr,
+							IMG_UINT32			ui32CleanupType);
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/env_data.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/env_data.h
new file mode 100644
index 0000000..a16a2fa
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/env_data.h
@@ -0,0 +1,62 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _ENV_DATA_
+#define _ENV_DATA_
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+#include <linux/workqueue.h>
+#endif
+
+#define PVRSRV_MAX_BRIDGE_IN_SIZE	0x1000
+#define PVRSRV_MAX_BRIDGE_OUT_SIZE	0x1000
+
+typedef	struct _PVR_PCI_DEV_TAG
+{
+	struct pci_dev		*psPCIDev;
+	HOST_PCI_INIT_FLAGS	ePCIFlags;
+	IMG_BOOL abPCIResourceInUse[DEVICE_COUNT_RESOURCE];
+} PVR_PCI_DEV;
+
+typedef struct _ENV_DATA_TAG
+{
+	IMG_VOID		*pvBridgeData;
+	struct pm_dev		*psPowerDevice;
+	IMG_BOOL		bLISRInstalled;
+	IMG_BOOL		bMISRInstalled;
+	IMG_UINT32		ui32IRQ;
+	IMG_VOID		*pvISRCookie;
+#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+	struct workqueue_struct	*psWorkQueue;
+#endif
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+	struct work_struct	sMISRWork;
+	IMG_VOID		*pvMISRData;
+#else
+	struct tasklet_struct	sMISRTasklet;
+#endif
+} ENV_DATA;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/env_perproc.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/env_perproc.h
new file mode 100644
index 0000000..c9fbad9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/env_perproc.h
@@ -0,0 +1,52 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __ENV_PERPROC_H__
+#define __ENV_PERPROC_H__
+
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+
+#include "services.h"
+#include "handle.h"
+
+typedef struct _PVRSRV_ENV_PER_PROCESS_DATA_
+{
+	IMG_HANDLE hBlockAlloc;
+	struct proc_dir_entry *psProcDir;
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+	struct list_head sDRMAuthListHead;
+#endif
+} PVRSRV_ENV_PER_PROCESS_DATA;
+
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+PVRSRV_ERROR LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+IMG_VOID LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
+
+IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/event.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/event.c
new file mode 100644
index 0000000..85493c1
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/event.c
@@ -0,0 +1,267 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION 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(2,6,22))
+#include <asm/system.h>
+#endif
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "proc.h"
+#include "mutex.h"
+#include "lock.h"
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_LIST_TAG
+{
+   rwlock_t 			   sLock;
+   struct list_head        sList;
+
+} PVRSRV_LINUX_EVENT_OBJECT_LIST;
+
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_TAG
+{
+	atomic_t	sTimeStamp;
+	IMG_UINT32  ui32TimeStampPrevious;
+#if defined(DEBUG)
+	IMG_UINT	ui32Stats;
+#endif
+    wait_queue_head_t sWait;
+	struct list_head        sList;
+	IMG_HANDLE				hResItem;
+	PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList;
+} PVRSRV_LINUX_EVENT_OBJECT;
+
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList)
+{
+	PVRSRV_LINUX_EVENT_OBJECT_LIST *psEvenObjectList;
+
+	if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST),
+		(IMG_VOID **)&psEvenObjectList, IMG_NULL,
+		"Linux Event Object List") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectCreate: failed to allocate memory for event list"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+    INIT_LIST_HEAD(&psEvenObjectList->sList);
+
+	rwlock_init(&psEvenObjectList->sLock);
+
+	*phEventObjectList = (IMG_HANDLE *) psEvenObjectList;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList)
+{
+
+	PVRSRV_LINUX_EVENT_OBJECT_LIST *psEvenObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST *) hEventObjectList ;
+
+	if(psEvenObjectList)
+	{
+		if (!list_empty(&psEvenObjectList->sList))
+		{
+			 PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectListDestroy: Event List is not empty"));
+			 return PVRSRV_ERROR_GENERIC;
+		}
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST), psEvenObjectList, IMG_NULL);
+
+	}
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject)
+{
+	if(hOSEventObjectList)
+	{
+		if(hOSEventObject)
+		{
+			PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)hOSEventObject;
+#if defined(DEBUG)
+			PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectListDelete: Event object waits: %lu", psLinuxEventObject->ui32Stats));
+#endif
+			if(ResManFreeResByPtr(psLinuxEventObject->hResItem) != PVRSRV_OK)
+			{
+				return PVRSRV_ERROR_GENERIC;
+			}
+
+			return PVRSRV_OK;
+		}
+	}
+	return PVRSRV_ERROR_GENERIC;
+
+}
+
+static PVRSRV_ERROR LinuxEventObjectDeleteCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+	PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = pvParam;
+	PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = psLinuxEventObject->psLinuxEventObjectList;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+	write_lock_bh(&psLinuxEventObjectList->sLock);
+	list_del(&psLinuxEventObject->sList);
+	write_unlock_bh(&psLinuxEventObjectList->sLock);
+
+#if defined(DEBUG)
+	PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectDeleteCallback: Event object waits: %lu", psLinuxEventObject->ui32Stats));
+#endif
+
+	OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), psLinuxEventObject, IMG_NULL);
+
+
+	return PVRSRV_OK;
+}
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject)
+ {
+	PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+	PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList;
+	IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+	PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+	psPerProc = PVRSRVPerProcessData(ui32PID);
+	if (psPerProc == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: Couldn't find per-process data"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+
+	if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT),
+		(IMG_VOID **)&psLinuxEventObject, IMG_NULL,
+		"Linux Event Object") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed to allocate memory "));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	INIT_LIST_HEAD(&psLinuxEventObject->sList);
+
+	atomic_set(&psLinuxEventObject->sTimeStamp, 0);
+	psLinuxEventObject->ui32TimeStampPrevious = 0;
+
+#if defined(DEBUG)
+	psLinuxEventObject->ui32Stats = 0;
+#endif
+    init_waitqueue_head(&psLinuxEventObject->sWait);
+
+	psLinuxEventObject->psLinuxEventObjectList = psLinuxEventObjectList;
+
+	psLinuxEventObject->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+													 RESMAN_TYPE_EVENT_OBJECT,
+													 psLinuxEventObject,
+													 0,
+													 &LinuxEventObjectDeleteCallback);
+
+	write_lock_bh(&psLinuxEventObjectList->sLock);
+	list_add(&psLinuxEventObject->sList, &psLinuxEventObjectList->sList);
+    write_unlock_bh(&psLinuxEventObjectList->sLock);
+
+	*phOSEventObject = psLinuxEventObject;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList)
+{
+	PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+	PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList;
+	struct list_head *psListEntry, *psListEntryTemp, *psList;
+	psList = &psLinuxEventObjectList->sList;
+
+	read_lock(&psLinuxEventObjectList->sLock);
+	list_for_each_safe(psListEntry, psListEntryTemp, psList)
+	{
+
+		psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)list_entry(psListEntry, PVRSRV_LINUX_EVENT_OBJECT, sList);
+
+		atomic_inc(&psLinuxEventObject->sTimeStamp);
+	 	wake_up_interruptible(&psLinuxEventObject->sWait);
+	}
+	read_unlock(&psLinuxEventObjectList->sLock);
+
+	return 	PVRSRV_OK;
+
+}
+
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout)
+{
+	IMG_UINT32 ui32TimeStamp;
+	DEFINE_WAIT(sWait);
+
+	PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *) hOSEventObject;
+
+	IMG_UINT32 ui32TimeOutJiffies = msecs_to_jiffies(ui32MSTimeout);
+
+	do
+	{
+		prepare_to_wait(&psLinuxEventObject->sWait, &sWait, TASK_INTERRUPTIBLE);
+		ui32TimeStamp = atomic_read(&psLinuxEventObject->sTimeStamp);
+
+		if(psLinuxEventObject->ui32TimeStampPrevious != ui32TimeStamp)
+		{
+			break;
+		}
+
+		mutex_unlock(&gPVRSRVLock);
+
+		ui32TimeOutJiffies = (IMG_UINT32)schedule_timeout((IMG_INT32)ui32TimeOutJiffies);
+
+		mutex_lock(&gPVRSRVLock);
+#if defined(DEBUG)
+		psLinuxEventObject->ui32Stats++;
+#endif
+
+
+	} while (ui32TimeOutJiffies);
+
+	finish_wait(&psLinuxEventObject->sWait, &sWait);
+
+	psLinuxEventObject->ui32TimeStampPrevious = ui32TimeStamp;
+
+	return ui32TimeOutJiffies ? PVRSRV_OK : PVRSRV_ERROR_TIMEOUT;
+
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/event.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/event.h
new file mode 100644
index 0000000..908014e
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/event.h
@@ -0,0 +1,28 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList);
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList);
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject);
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject);
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList);
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout);
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/kbuild/Makefile b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/kbuild/Makefile
new file mode 100644
index 0000000..887689f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/kbuild/Makefile
@@ -0,0 +1,151 @@
+#
+# Copyright (c) Imagination Technologies Ltd.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE. 
+# 
+#
+
+MODULE		?= pvrsrvkm
+
+MODULE_CFLAGS = 
+
+ifeq ($(PVR_KBUILD_IN_KERNEL),1)
+# PVRKROOT is the relative path to the PVR sources.
+# DRVKROOT should point to the non-PVR sources, if any.
+PVRKROOT ?= .
+KBUILDROOT 	= $(PVRKROOT)/services4
+else
+KBUILDROOT 	= ../../../..
+endif
+
+clean-dirs :=
+
+INCLUDES = 	-I$(EURASIAROOT)/include4 \
+			-I$(EURASIAROOT)/services4/include \
+			-I$(EURASIAROOT)/services4/srvkm/env/linux \
+			-I$(EURASIAROOT)/services4/srvkm/include \
+			-I$(EURASIAROOT)/services4/srvkm/bridged \
+			-I$(EURASIAROOT)/services4/system/include \
+			-I$(EURASIAROOT)/services4/system/plb \
+			-I$(EURASIAROOT)/services4/system/tnc 
+
+
+SOURCES	      = $(KBUILDROOT)/srvkm/env/linux/osfunc.c \
+				$(KBUILDROOT)/srvkm/env/linux/mutils.c \
+				$(KBUILDROOT)/srvkm/env/linux/mmap.c \
+				$(KBUILDROOT)/srvkm/env/linux/module.c \
+				$(KBUILDROOT)/srvkm/env/linux/pdump.c \
+				$(KBUILDROOT)/srvkm/env/linux/proc.c \
+				$(KBUILDROOT)/srvkm/env/linux/pvr_bridge_k.c \
+				$(KBUILDROOT)/srvkm/env/linux/pvr_debug.c \
+				$(KBUILDROOT)/srvkm/env/linux/mm.c \
+				$(KBUILDROOT)/srvkm/env/linux/mutex.c \
+				$(KBUILDROOT)/srvkm/env/linux/event.c \
+				$(KBUILDROOT)/srvkm/env/linux/osperproc.c
+
+SOURCES	     += $(KBUILDROOT)/srvkm/common/buffer_manager.c \
+				$(KBUILDROOT)/srvkm/common/devicemem.c \
+				$(KBUILDROOT)/srvkm/common/deviceclass.c \
+				$(KBUILDROOT)/srvkm/common/handle.c \
+				$(KBUILDROOT)/srvkm/common/hash.c \
+				$(KBUILDROOT)/srvkm/common/metrics.c \
+				$(KBUILDROOT)/srvkm/common/pvrsrv.c \
+				$(KBUILDROOT)/srvkm/common/queue.c \
+				$(KBUILDROOT)/srvkm/common/ra.c \
+				$(KBUILDROOT)/srvkm/common/resman.c \
+				$(KBUILDROOT)/srvkm/common/power.c \
+				$(KBUILDROOT)/srvkm/common/mem.c \
+				$(KBUILDROOT)/srvkm/common/pdump_common.c \
+				$(KBUILDROOT)/srvkm/bridged/bridged_support.c \
+				$(KBUILDROOT)/srvkm/bridged/bridged_pvr_bridge.c \
+				$(KBUILDROOT)/srvkm/common/perproc.c \
+				$(KBUILDROOT)/../services4/system/plb/sysconfig.c \
+				$(KBUILDROOT)/../services4/system/tnc/sysconfig.c \
+				$(KBUILDROOT)/../services4/system/common/sysconfig.c \
+				$(KBUILDROOT)/../services4/system/common/sysutils.c \
+				$(KBUILDROOT)/srvkm/common/lists.c \
+				$(KBUILDROOT)/srvkm/common/mem_debug.c
+
+INCLUDES += -I$(EURASIAROOT)/services4/srvkm/hwdefs 
+
+SYM_VERS_DEPS = $(EURASIAROOT)/tools/intern/debug/dbgdriv/linux
+
+
+#
+# Device dependent
+#
+
+ifeq ($(SUPPORT_SGX), 1)
+
+INCLUDES 	+=	-I$(EURASIAROOT)/services4/srvkm/bridged/sgx \
+				-I$(EURASIAROOT)/services4/srvkm/devices/sgx
+
+SOURCES		+= 	$(KBUILDROOT)/srvkm/bridged/sgx/bridged_sgx_bridge.c \
+				$(KBUILDROOT)/srvkm/devices/sgx/sgxinit.c \
+				$(KBUILDROOT)/srvkm/devices/sgx/sgxpower.c \
+				$(KBUILDROOT)/srvkm/devices/sgx/sgxreset.c \
+				$(KBUILDROOT)/srvkm/devices/sgx/sgxutils.c \
+				$(KBUILDROOT)/srvkm/devices/sgx/sgxkick.c \
+				$(KBUILDROOT)/srvkm/devices/sgx/sgxtransfer.c \
+				$(KBUILDROOT)/srvkm/devices/sgx/mmu.c \
+				$(KBUILDROOT)/srvkm/devices/sgx/pb.c
+
+else  
+
+ifeq ($(SUPPORT_VGX), 1)
+
+INCLUDES 	+=	-I$(EURASIAROOT)/services4/srvkm/bridged/vgx \
+				-I$(EURASIAROOT)/services4/srvkm/devices/vgx
+
+#FIXME: We need to cerate a subset of vgxdefs.h from $(EURASIAROOT)/hwdefs 
+# and put it into srvkm/hwdefs for GPL compliance
+INCLUDES 	+=	-I$(EURASIAROOT)/hwdefs
+
+SOURCES		+= 	$(KBUILDROOT)/srvkm/bridged/vgx/bridged_vgx_bridge.c \
+				$(KBUILDROOT)/srvkm/devices/vgx/vgxinit.c \
+				$(KBUILDROOT)/srvkm/devices/vgx/vgxreset.c \
+				$(KBUILDROOT)/srvkm/devices/vgx/mmu.c \
+				$(KBUILDROOT)/srvkm/devices/vgx/pb.c \
+				$(KBUILDROOT)/srvkm/env/linux/pdump_vgx.c
+endif
+
+endif # SUPPORT_SGX
+
+ifeq ($(SUPPORT_DRI_DRM),1)
+	SOURCES += $(KBUILDROOT)/srvkm/env/linux/pvr_drm.c
+	INCLUDES += -I$(KERNELDIR)/include/drm \
+		-I$(EURASIAROOT)/services4/include/env/linux
+
+ifneq ("$(DISPLAY_CONTROLLER_DIR)","")
+include $(EURASIAROOT)/services4/$(DISPLAY_CONTROLLER_DIR)/makefile.linux.common
+endif
+
+ifeq ($(PDUMP),1)
+include $(EURASIAROOT)/tools/intern/debug/dbgdriv/linux/makefile.linux.common
+endif
+
+endif
+
+ifeq ($(PVR_MODULE_TEST),1)
+INCLUDES += -I$(EURASIAROOT)/moduletests/include
+SOURCES	 += $(KBUILDROOT)/../moduletests/services_test/kern_test.c
+SYS_CFLAGS += -DMODULE_TEST
+endif
+
+include $(EURASIAROOT)/eurasiacon/build/linux/kbuild/Makefile.kbuild_subdir_common
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/linkage.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/linkage.h
new file mode 100644
index 0000000..a124f78
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/linkage.h
@@ -0,0 +1,57 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __LINKAGE_H__
+#define __LINKAGE_H__
+
+#if !defined(SUPPORT_DRI_DRM)
+IMG_INT32 PVRSRV_BridgeDispatchKM(struct file *file, IMG_UINT cmd, IMG_UINT32 arg);
+#endif
+
+IMG_VOID PVRDPFInit(IMG_VOID);
+PVRSRV_ERROR PVROSFuncInit(IMG_VOID);
+IMG_VOID PVROSFuncDeInit(IMG_VOID);
+
+#ifdef DEBUG
+IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data);
+IMG_VOID PVRDebugSetLevel(IMG_UINT32 uDebugLevel);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el);
+#else
+IMG_INT PVRDebugProcGetLevel(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data);
+#endif
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el);
+#else
+IMG_INT PVRProcGetPowerLevel(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data);
+#endif
+
+
+#endif
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/lock.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/lock.h
new file mode 100644
index 0000000..4a18e01
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/lock.h
@@ -0,0 +1,28 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __LOCK_H__
+#define __LOCK_H__
+
+extern struct mutex gPVRSRVLock;
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mm.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mm.c
new file mode 100644
index 0000000..8844f0a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mm.c
@@ -0,0 +1,2377 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+#include <linux/wrapper.h>
+#endif
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/sched.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "sysconfig.h"
+#include "mutils.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "mutex.h"
+#include "lock.h"
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+	#include "lists.h"
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+typedef enum {
+    DEBUG_MEM_ALLOC_TYPE_KMALLOC,
+    DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+    DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+    DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+    DEBUG_MEM_ALLOC_TYPE_IO,
+    DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+    DEBUG_MEM_ALLOC_TYPE_COUNT
+}DEBUG_MEM_ALLOC_TYPE;
+
+typedef struct _DEBUG_MEM_ALLOC_REC
+{
+    DEBUG_MEM_ALLOC_TYPE    eAllocType;
+	IMG_VOID				*pvKey;
+    IMG_VOID                *pvCpuVAddr;
+    IMG_UINT32              ulCpuPAddr;
+    IMG_VOID                *pvPrivateData;
+	IMG_UINT32				ui32Bytes;
+	pid_t					pid;
+    IMG_CHAR                *pszFileName;
+    IMG_UINT32              ui32Line;
+
+    struct _DEBUG_MEM_ALLOC_REC   *psNext;
+	struct _DEBUG_MEM_ALLOC_REC   **ppsThis;
+}DEBUG_MEM_ALLOC_REC;
+
+static IMPLEMENT_LIST_ANY_VA_2(DEBUG_MEM_ALLOC_REC, IMG_BOOL, IMG_FALSE)
+static IMPLEMENT_LIST_ANY_VA(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_FOR_EACH(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_INSERT(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_REMOVE(DEBUG_MEM_ALLOC_REC)
+
+
+static DEBUG_MEM_ALLOC_REC *g_MemoryRecords;
+
+static IMG_UINT32 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
+static IMG_UINT32 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
+
+static IMG_UINT32 g_SysRAMWaterMark;
+static IMG_UINT32 g_SysRAMHighWaterMark;
+
+static IMG_UINT32 g_IOMemWaterMark;
+static IMG_UINT32 g_IOMemHighWaterMark;
+
+static IMG_VOID DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
+                                       IMG_VOID *pvKey,
+                                       IMG_VOID *pvCpuVAddr,
+                                       IMG_UINT32 ulCpuPAddr,
+                                       IMG_VOID *pvPrivateData,
+                                       IMG_UINT32 ui32Bytes,
+                                       IMG_CHAR *pszFileName,
+                                       IMG_UINT32 ui32Line);
+
+static IMG_VOID DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+static IMG_CHAR *DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType);
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+static struct proc_dir_entry *g_SeqFileMemoryRecords =0;
+static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementMemoryRecords(struct seq_file * sfile, loff_t off);
+
+#else
+static off_t printMemoryRecords(IMG_CHAR * buffer, size_t size, off_t off);
+#endif
+
+#endif
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+typedef struct _DEBUG_LINUX_MEM_AREA_REC
+{
+	LinuxMemArea                *psLinuxMemArea;
+    IMG_UINT32                  ui32Flags;
+	pid_t					    pid;
+
+	struct _DEBUG_LINUX_MEM_AREA_REC  *psNext;
+	struct _DEBUG_LINUX_MEM_AREA_REC  **ppsThis;
+}DEBUG_LINUX_MEM_AREA_REC;
+
+
+static IMPLEMENT_LIST_ANY_VA(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_FOR_EACH(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_INSERT(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_REMOVE(DEBUG_LINUX_MEM_AREA_REC)
+
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static struct mutex g_sDebugMutex;
+#endif
+
+static DEBUG_LINUX_MEM_AREA_REC *g_LinuxMemAreaRecords;
+static IMG_UINT32 g_LinuxMemAreaCount;
+static IMG_UINT32 g_LinuxMemAreaWaterMark;
+static IMG_UINT32 g_LinuxMemAreaHighWaterMark;
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+static struct proc_dir_entry *g_SeqFileMemArea=0;
+
+static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowMemArea(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementMemArea(struct seq_file *sfile, loff_t off);
+
+#else
+static off_t printLinuxMemAreaRecords(IMG_CHAR * buffer, size_t size, off_t off);
+#endif
+
+#endif
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+#if (defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS))
+static void ProcSeqStartstopDebugMutex(struct seq_file *sfile,IMG_BOOL start);
+#endif
+#endif
+
+static LinuxKMemCache *psLinuxMemAreaCache;
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+static IMG_VOID ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length);
+static IMG_VOID UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length);
+#endif
+
+static LinuxMemArea *LinuxMemAreaStructAlloc(IMG_VOID);
+static IMG_VOID LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea);
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags);
+static DEBUG_LINUX_MEM_AREA_REC *DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea);
+static IMG_VOID DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea);
+#endif
+
+PVRSRV_ERROR
+LinuxMMInit(IMG_VOID)
+{
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+	mutex_init(&g_sDebugMutex);
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    {
+        IMG_INT iStatus;
+#ifdef PVR_PROC_USE_SEQ_FILE
+		g_SeqFileMemArea = CreateProcReadEntrySeq(
+									"mem_areas",
+									NULL,
+									ProcSeqNextMemArea,
+									ProcSeqShowMemArea,
+									ProcSeqOff2ElementMemArea,
+									ProcSeqStartstopDebugMutex
+								   );
+		iStatus = !g_SeqFileMemArea ? -1 : 0;
+#else
+   iStatus = CreateProcReadEntry("mem_areas", printLinuxMemAreaRecords);
+#endif
+        if(iStatus!=0)
+        {
+            return PVRSRV_ERROR_OUT_OF_MEMORY;
+        }
+    }
+#endif
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    {
+        IMG_INT iStatus;
+#ifdef PVR_PROC_USE_SEQ_FILE
+		g_SeqFileMemoryRecords =CreateProcReadEntrySeq(
+									"meminfo",
+									NULL,
+									ProcSeqNextMemoryRecords,
+									ProcSeqShowMemoryRecords,
+									ProcSeqOff2ElementMemoryRecords,
+									ProcSeqStartstopDebugMutex
+								   );
+
+		iStatus = !g_SeqFileMemoryRecords ? -1 : 0;
+#else
+        iStatus = CreateProcReadEntry("meminfo", printMemoryRecords);
+#endif
+        if(iStatus!=0)
+        {
+            return PVRSRV_ERROR_OUT_OF_MEMORY;
+        }
+    }
+#endif
+
+    psLinuxMemAreaCache = KMemCacheCreateWrapper("img-mm", sizeof(LinuxMemArea), 0, 0);
+    if(!psLinuxMemAreaCache)
+    {
+        PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
+        return PVRSRV_ERROR_OUT_OF_MEMORY;
+    }
+
+    return PVRSRV_OK;
+}
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+IMG_VOID LinuxMMCleanup_MemAreas_ForEachCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord)
+{
+	LinuxMemArea *psLinuxMemArea;
+
+	psLinuxMemArea = psCurrentRecord->psLinuxMemArea;
+	PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up Linux memory area (%p), type=%s, size=%ld bytes",
+				__FUNCTION__,
+				psCurrentRecord->psLinuxMemArea,
+				LinuxMemAreaTypeToString(psCurrentRecord->psLinuxMemArea->eAreaType),
+				psCurrentRecord->psLinuxMemArea->ui32ByteSize));
+
+	LinuxMemAreaDeepFree(psLinuxMemArea);
+}
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+IMG_VOID LinuxMMCleanup_MemRecords_ForEachVa(DEBUG_MEM_ALLOC_REC *psCurrentRecord)
+
+{
+
+	PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: "
+							"type=%s "
+							"CpuVAddr=%p "
+							"CpuPAddr=0x%08lx, "
+							"allocated @ file=%s,line=%d",
+			__FUNCTION__,
+			DebugMemAllocRecordTypeToString(psCurrentRecord->eAllocType),
+			psCurrentRecord->pvCpuVAddr,
+			psCurrentRecord->ulCpuPAddr,
+			psCurrentRecord->pszFileName,
+			psCurrentRecord->ui32Line));
+	switch(psCurrentRecord->eAllocType)
+	{
+		case DEBUG_MEM_ALLOC_TYPE_KMALLOC:
+			KFreeWrapper(psCurrentRecord->pvCpuVAddr);
+			break;
+		case DEBUG_MEM_ALLOC_TYPE_IOREMAP:
+			IOUnmapWrapper(psCurrentRecord->pvCpuVAddr);
+			break;
+		case DEBUG_MEM_ALLOC_TYPE_IO:
+
+			DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO, psCurrentRecord->pvKey, __FILE__, __LINE__);
+			break;
+		case DEBUG_MEM_ALLOC_TYPE_VMALLOC:
+			VFreeWrapper(psCurrentRecord->pvCpuVAddr);
+			break;
+		case DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES:
+
+			DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, psCurrentRecord->pvKey, __FILE__, __LINE__);
+			break;
+		case DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE:
+			KMemCacheFreeWrapper(psCurrentRecord->pvPrivateData, psCurrentRecord->pvCpuVAddr);
+			break;
+		default:
+			PVR_ASSERT(0);
+	}
+}
+#endif
+
+
+IMG_VOID
+LinuxMMCleanup(IMG_VOID)
+{
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    {
+        if(g_LinuxMemAreaCount)
+        {
+            PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: There are %d LinuxMemArea allocation unfreed (%ld bytes)",
+                    __FUNCTION__, g_LinuxMemAreaCount, g_LinuxMemAreaWaterMark));
+        }
+
+		List_DEBUG_LINUX_MEM_AREA_REC_ForEach(g_LinuxMemAreaRecords,
+											LinuxMMCleanup_MemAreas_ForEachCb);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+		RemoveProcEntrySeq( g_SeqFileMemArea );
+#else
+        RemoveProcEntry("mem_areas");
+#endif
+    }
+#endif
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    {
+
+
+		List_DEBUG_MEM_ALLOC_REC_ForEach(g_MemoryRecords,
+										LinuxMMCleanup_MemRecords_ForEachVa);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+		RemoveProcEntrySeq( g_SeqFileMemoryRecords );
+#else
+        RemoveProcEntry("meminfo");
+#endif
+
+    }
+#endif
+
+    if(psLinuxMemAreaCache)
+    {
+        KMemCacheDestroyWrapper(psLinuxMemAreaCache);
+        psLinuxMemAreaCache=NULL;
+    }
+}
+
+
+IMG_VOID *
+_KMallocWrapper(IMG_UINT32 ui32ByteSize, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+    IMG_VOID *pvRet;
+    pvRet = kmalloc(ui32ByteSize, GFP_KERNEL);
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    if(pvRet)
+    {
+        DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMALLOC,
+                               pvRet,
+                               pvRet,
+                               0,
+                               NULL,
+                               ui32ByteSize,
+                               pszFileName,
+                               ui32Line
+                               );
+    }
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+    return pvRet;
+}
+
+
+IMG_VOID
+_KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMALLOC, pvCpuVAddr, pszFileName,  ui32Line);
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+    kfree(pvCpuVAddr);
+}
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static IMG_VOID
+DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
+                       IMG_VOID *pvKey,
+                       IMG_VOID *pvCpuVAddr,
+                       IMG_UINT32 ulCpuPAddr,
+                       IMG_VOID *pvPrivateData,
+                       IMG_UINT32 ui32Bytes,
+                       IMG_CHAR *pszFileName,
+                       IMG_UINT32 ui32Line)
+{
+    DEBUG_MEM_ALLOC_REC *psRecord;
+
+    mutex_lock(&g_sDebugMutex);
+
+    psRecord = kmalloc(sizeof(DEBUG_MEM_ALLOC_REC), GFP_KERNEL);
+
+    psRecord->eAllocType = eAllocType;
+    psRecord->pvKey = pvKey;
+    psRecord->pvCpuVAddr = pvCpuVAddr;
+    psRecord->ulCpuPAddr = ulCpuPAddr;
+    psRecord->pvPrivateData = pvPrivateData;
+    psRecord->pid = current->pid;
+    psRecord->ui32Bytes = ui32Bytes;
+    psRecord->pszFileName = pszFileName;
+    psRecord->ui32Line = ui32Line;
+
+	List_DEBUG_MEM_ALLOC_REC_Insert(&g_MemoryRecords, psRecord);
+
+    g_WaterMarkData[eAllocType] += ui32Bytes;
+    if(g_WaterMarkData[eAllocType] > g_HighWaterMarkData[eAllocType])
+    {
+        g_HighWaterMarkData[eAllocType] = g_WaterMarkData[eAllocType];
+    }
+
+    if(eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
+       || eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
+       || eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
+       || eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+    {
+        g_SysRAMWaterMark += ui32Bytes;
+        if(g_SysRAMWaterMark > g_SysRAMHighWaterMark)
+        {
+            g_SysRAMHighWaterMark = g_SysRAMWaterMark;
+        }
+    }
+    else if(eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+            || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
+    {
+        g_IOMemWaterMark += ui32Bytes;
+        if(g_IOMemWaterMark > g_IOMemHighWaterMark)
+        {
+            g_IOMemHighWaterMark = g_IOMemWaterMark;
+        }
+    }
+
+    mutex_unlock(&g_sDebugMutex);
+}
+
+
+IMG_BOOL DebugMemAllocRecordRemove_AnyVaCb(DEBUG_MEM_ALLOC_REC *psCurrentRecord, va_list va)
+{
+	DEBUG_MEM_ALLOC_TYPE eAllocType;
+	IMG_VOID *pvKey;
+
+	eAllocType = va_arg(va, DEBUG_MEM_ALLOC_TYPE);
+	pvKey = va_arg(va, IMG_VOID*);
+
+	if(psCurrentRecord->eAllocType == eAllocType
+		&& psCurrentRecord->pvKey == pvKey)
+	{
+		eAllocType = psCurrentRecord->eAllocType;
+		g_WaterMarkData[eAllocType] -= psCurrentRecord->ui32Bytes;
+
+		if(eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
+		   || eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
+		   || eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
+		   || eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+		{
+			g_SysRAMWaterMark -= psCurrentRecord->ui32Bytes;
+		}
+		else if(eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+				|| eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
+		{
+			g_IOMemWaterMark -= psCurrentRecord->ui32Bytes;
+		}
+
+		List_DEBUG_MEM_ALLOC_REC_Remove(psCurrentRecord);
+		kfree(psCurrentRecord);
+
+		return IMG_TRUE;
+	}
+	else
+	{
+		return IMG_FALSE;
+	}
+}
+
+
+static IMG_VOID
+DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+    mutex_lock(&g_sDebugMutex);
+
+
+	if(!List_DEBUG_MEM_ALLOC_REC_IMG_BOOL_Any_va(g_MemoryRecords,
+												DebugMemAllocRecordRemove_AnyVaCb,
+												eAllocType,
+												pvKey))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for type=%s with pvKey=%p (called from %s, line %d\n",
+		__FUNCTION__, DebugMemAllocRecordTypeToString(eAllocType), pvKey,
+		pszFileName, ui32Line));
+	}
+
+    mutex_unlock(&g_sDebugMutex);
+}
+
+
+static IMG_CHAR *
+DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType)
+{
+    IMG_CHAR *apszDebugMemoryRecordTypes[] = {
+        "KMALLOC",
+        "VMALLOC",
+        "ALLOC_PAGES",
+        "IOREMAP",
+        "IO",
+        "KMEM_CACHE_ALLOC"
+    };
+    return apszDebugMemoryRecordTypes[eAllocType];
+}
+#endif
+
+
+
+IMG_VOID *
+_VMallocWrapper(IMG_UINT32 ui32Bytes,
+                IMG_UINT32 ui32AllocFlags,
+                IMG_CHAR *pszFileName,
+                IMG_UINT32 ui32Line)
+{
+    pgprot_t PGProtFlags;
+    IMG_VOID *pvRet;
+
+    switch(ui32AllocFlags & PVRSRV_HAP_CACHETYPE_MASK)
+    {
+        case PVRSRV_HAP_CACHED:
+            PGProtFlags = PAGE_KERNEL;
+            break;
+        case PVRSRV_HAP_WRITECOMBINE:
+            PGProtFlags = PGPROT_WC(PAGE_KERNEL);
+            break;
+        case PVRSRV_HAP_UNCACHED:
+            PGProtFlags = PGPROT_UC(PAGE_KERNEL);
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR,
+                     "VMAllocWrapper: unknown mapping flags=0x%08lx",
+                     ui32AllocFlags));
+            dump_stack();
+            return NULL;
+    }
+
+
+    pvRet = __vmalloc(ui32Bytes, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    if(pvRet)
+    {
+        DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+                               pvRet,
+                               pvRet,
+                               0,
+                               NULL,
+                               PAGE_ALIGN(ui32Bytes),
+                               pszFileName,
+                               ui32Line
+                               );
+    }
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+    return pvRet;
+}
+
+
+IMG_VOID
+_VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMALLOC, pvCpuVAddr, pszFileName, ui32Line);
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+    vfree(pvCpuVAddr);
+}
+
+
+LinuxMemArea *
+NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
+{
+    LinuxMemArea *psLinuxMemArea;
+    IMG_VOID *pvCpuVAddr;
+
+    psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if(!psLinuxMemArea)
+    {
+        goto failed;
+    }
+
+    pvCpuVAddr = VMallocWrapper(ui32Bytes, ui32AreaFlags);
+    if(!pvCpuVAddr)
+    {
+        goto failed;
+    }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+
+    ReservePages(pvCpuVAddr, ui32Bytes);
+#endif
+
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_VMALLOC;
+    psLinuxMemArea->uData.sVmalloc.pvVmallocAddress = pvCpuVAddr;
+    psLinuxMemArea->ui32ByteSize = ui32Bytes;
+    psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+    psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+    return psLinuxMemArea;
+
+failed:
+    PVR_DPF((PVR_DBG_ERROR, "%s: failed!", __FUNCTION__));
+    if(psLinuxMemArea)
+        LinuxMemAreaStructFree(psLinuxMemArea);
+    return NULL;
+}
+
+
+IMG_VOID
+FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVR_ASSERT(psLinuxMemArea);
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_VMALLOC);
+    PVR_ASSERT(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+	UnreservePages(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress,
+                    psLinuxMemArea->ui32ByteSize);
+#endif
+
+    PVR_DPF((PVR_DBG_MESSAGE,"%s: pvCpuVAddr: %p",
+             __FUNCTION__, psLinuxMemArea->uData.sVmalloc.pvVmallocAddress));
+    VFreeWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+static IMG_VOID
+ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
+{
+	IMG_VOID *pvPage;
+	IMG_VOID *pvEnd = pvAddress + ui32Length;
+
+	for(pvPage = pvAddress; pvPage < pvEnd;  pvPage += PAGE_SIZE)
+	{
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+		SetPageReserved(vmalloc_to_page(pvPage));
+#else
+		mem_map_reserve(vmalloc_to_page(pvPage));
+#endif
+	}
+}
+
+
+static IMG_VOID
+UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
+{
+	IMG_VOID *pvPage;
+	IMG_VOID *pvEnd = pvAddress + ui32Length;
+
+	for(pvPage = pvAddress; pvPage < pvEnd;  pvPage += PAGE_SIZE)
+	{
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+		ClearPageReserved(vmalloc_to_page(pvPage));
+#else
+		mem_map_unreserve(vmalloc_to_page(pvPage));
+#endif
+	}
+}
+#endif
+
+
+IMG_VOID *
+_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
+               IMG_UINT32 ui32Bytes,
+               IMG_UINT32 ui32MappingFlags,
+               IMG_CHAR *pszFileName,
+               IMG_UINT32 ui32Line)
+{
+    IMG_VOID *pvIORemapCookie;
+
+    switch(ui32MappingFlags & PVRSRV_HAP_CACHETYPE_MASK)
+    {
+        case PVRSRV_HAP_CACHED:
+	    pvIORemapCookie = (IMG_VOID *)IOREMAP(BasePAddr.uiAddr, ui32Bytes);
+            break;
+        case PVRSRV_HAP_WRITECOMBINE:
+	    pvIORemapCookie = (IMG_VOID *)IOREMAP_WC(BasePAddr.uiAddr, ui32Bytes);
+            break;
+        case PVRSRV_HAP_UNCACHED:
+            pvIORemapCookie = (IMG_VOID *)IOREMAP_UC(BasePAddr.uiAddr, ui32Bytes);
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "IORemapWrapper: unknown mapping flags"));
+            return NULL;
+    }
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    if(pvIORemapCookie)
+    {
+        DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+                               pvIORemapCookie,
+                               pvIORemapCookie,
+                               BasePAddr.uiAddr,
+                               NULL,
+                               ui32Bytes,
+                               pszFileName,
+                               ui32Line
+                               );
+    }
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+    return pvIORemapCookie;
+}
+
+
+IMG_VOID
+_IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IOREMAP, pvIORemapCookie, pszFileName, ui32Line);
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+    iounmap(pvIORemapCookie);
+}
+
+
+LinuxMemArea *
+NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
+                       IMG_UINT32 ui32Bytes,
+                       IMG_UINT32 ui32AreaFlags)
+{
+    LinuxMemArea *psLinuxMemArea;
+    IMG_VOID *pvIORemapCookie;
+
+    psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if(!psLinuxMemArea)
+    {
+        return NULL;
+    }
+
+    pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32AreaFlags);
+    if(!pvIORemapCookie)
+    {
+        LinuxMemAreaStructFree(psLinuxMemArea);
+        return NULL;
+    }
+
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IOREMAP;
+    psLinuxMemArea->uData.sIORemap.pvIORemapCookie = pvIORemapCookie;
+    psLinuxMemArea->uData.sIORemap.CPUPhysAddr = BasePAddr;
+    psLinuxMemArea->ui32ByteSize = ui32Bytes;
+    psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+    psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+    return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IOREMAP);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+    IOUnmapWrapper(psLinuxMemArea->uData.sIORemap.pvIORemapCookie);
+
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+static IMG_BOOL
+TreatExternalPagesAsContiguous(IMG_SYS_PHYADDR *psSysPhysAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig)
+{
+	IMG_UINT32 ui32;
+	IMG_UINT32 ui32AddrChk;
+	IMG_UINT32 ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+
+
+	for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+		ui32 < ui32NumPages;
+		ui32++, ui32AddrChk = (bPhysContig) ? (ui32AddrChk + PAGE_SIZE) : psSysPhysAddr[ui32].uiAddr)
+	{
+		if (!pfn_valid(PHYS_TO_PFN(ui32AddrChk)))
+		{
+			break;
+		}
+	}
+	if (ui32 == ui32NumPages)
+	{
+		return IMG_FALSE;
+	}
+
+	if (!bPhysContig)
+	{
+		for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+			ui32 < ui32NumPages;
+			ui32++, ui32AddrChk += PAGE_SIZE)
+		{
+			if (psSysPhysAddr[ui32].uiAddr != ui32AddrChk)
+			{
+				return IMG_FALSE;
+			}
+		}
+	}
+
+	return IMG_TRUE;
+}
+
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags)
+{
+    LinuxMemArea *psLinuxMemArea;
+
+    psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if(!psLinuxMemArea)
+    {
+        return NULL;
+    }
+
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_EXTERNAL_KV;
+    psLinuxMemArea->uData.sExternalKV.pvExternalKV = pvCPUVAddr;
+    psLinuxMemArea->uData.sExternalKV.bPhysContig = (IMG_BOOL)(bPhysContig || TreatExternalPagesAsContiguous(pBasePAddr, ui32Bytes, bPhysContig));
+
+    if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
+    {
+	psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr = *pBasePAddr;
+    }
+    else
+    {
+	psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr = pBasePAddr;
+    }
+    psLinuxMemArea->ui32ByteSize = ui32Bytes;
+    psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+    psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+    return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_EXTERNAL_KV);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+LinuxMemArea *
+NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
+                  IMG_UINT32 ui32Bytes,
+                  IMG_UINT32 ui32AreaFlags)
+{
+    LinuxMemArea *psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if(!psLinuxMemArea)
+    {
+        return NULL;
+    }
+
+
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IO;
+    psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr = BasePAddr.uiAddr;
+    psLinuxMemArea->ui32ByteSize = ui32Bytes;
+    psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+    psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IO,
+                           (IMG_VOID *)BasePAddr.uiAddr,
+                           0,
+                           BasePAddr.uiAddr,
+                           NULL,
+                           ui32Bytes,
+                           "unknown",
+                           0
+                           );
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+    return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IO);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO,
+                              (IMG_VOID *)psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr, __FILE__, __LINE__);
+#endif
+
+
+
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+LinuxMemArea *
+NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
+{
+    LinuxMemArea *psLinuxMemArea;
+    IMG_UINT32 ui32PageCount;
+    struct page **pvPageList;
+    IMG_HANDLE hBlockPageList;
+    IMG_INT32 i;
+    PVRSRV_ERROR eError;
+
+    psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if(!psLinuxMemArea)
+    {
+        goto failed_area_alloc;
+    }
+
+    ui32PageCount = RANGE_TO_PAGES(ui32Bytes);
+    eError = OSAllocMem(0, sizeof(*pvPageList) * ui32PageCount, (IMG_VOID **)&pvPageList, &hBlockPageList,
+							"Array of pages");
+    if(eError != PVRSRV_OK)
+    {
+        goto failed_page_list_alloc;
+    }
+
+    for(i=0; i<(IMG_INT32)ui32PageCount; i++)
+    {
+        pvPageList[i] = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
+        if(!pvPageList[i])
+        {
+            goto failed_alloc_pages;
+        }
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+	SetPageReserved(pvPageList[i]);
+#else
+        mem_map_reserve(pvPageList[i]);
+#endif
+#endif
+
+    }
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+                           pvPageList,
+                           0,
+                           0,
+                           NULL,
+                           PAGE_ALIGN(ui32Bytes),
+                           "unknown",
+                           0
+                           );
+#endif
+
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES;
+    psLinuxMemArea->uData.sPageList.pvPageList = pvPageList;
+    psLinuxMemArea->uData.sPageList.hBlockPageList = hBlockPageList;
+    psLinuxMemArea->ui32ByteSize = ui32Bytes;
+    psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+    psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+    return psLinuxMemArea;
+
+failed_alloc_pages:
+    for(i--; i >= 0; i--)
+    {
+        __free_pages(pvPageList[i], 0);
+    }
+    (IMG_VOID) OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList, hBlockPageList);
+	psLinuxMemArea->uData.sPageList.pvPageList = IMG_NULL;
+failed_page_list_alloc:
+    LinuxMemAreaStructFree(psLinuxMemArea);
+failed_area_alloc:
+    PVR_DPF((PVR_DBG_ERROR, "%s: failed", __FUNCTION__));
+
+    return NULL;
+}
+
+
+IMG_VOID
+FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    IMG_UINT32 ui32PageCount;
+    struct page **pvPageList;
+    IMG_HANDLE hBlockPageList;
+    IMG_INT32 i;
+
+    PVR_ASSERT(psLinuxMemArea);
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ALLOC_PAGES);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+    ui32PageCount = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
+    pvPageList = psLinuxMemArea->uData.sPageList.pvPageList;
+    hBlockPageList = psLinuxMemArea->uData.sPageList.hBlockPageList;
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, pvPageList, __FILE__, __LINE__);
+#endif
+
+    for(i=0;i<(IMG_INT32)ui32PageCount;i++)
+    {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+        ClearPageReserved(pvPageList[i]);
+#else
+        mem_map_reserve(pvPageList[i]);
+#endif
+#endif
+        __free_pages(pvPageList[i], 0);
+    }
+
+    (IMG_VOID) OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList, hBlockPageList);
+	psLinuxMemArea->uData.sPageList.pvPageList = IMG_NULL;
+
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+struct page*
+LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea,
+                         IMG_UINT32 ui32ByteOffset)
+{
+    IMG_UINT32 ui32PageIndex;
+    IMG_CHAR *pui8Addr;
+
+    switch(psLinuxMemArea->eAreaType)
+    {
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+            ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+            return psLinuxMemArea->uData.sPageList.pvPageList[ui32PageIndex];
+
+        case LINUX_MEM_AREA_VMALLOC:
+            pui8Addr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+            pui8Addr += ui32ByteOffset;
+            return vmalloc_to_page(pui8Addr);
+
+        case LINUX_MEM_AREA_SUB_ALLOC:
+
+            return LinuxMemAreaOffsetToPage(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
+                                            psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset
+                                             + ui32ByteOffset);
+        default:
+            PVR_DPF((PVR_DBG_ERROR,
+                    "%s: Unsupported request for struct page from LinuxMemArea with type=%s",
+                    __FUNCTION__, LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType)));
+            return NULL;
+    }
+}
+
+
+LinuxKMemCache *
+KMemCacheCreateWrapper(IMG_CHAR *pszName,
+                       size_t Size,
+                       size_t Align,
+                       IMG_UINT32 ui32Flags)
+{
+#if defined(DEBUG_LINUX_SLAB_ALLOCATIONS)
+    ui32Flags |= SLAB_POISON|SLAB_RED_ZONE;
+#endif
+    return kmem_cache_create(pszName, Size, Align, ui32Flags, NULL
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+				, NULL
+#endif
+			    );
+}
+
+
+IMG_VOID
+KMemCacheDestroyWrapper(LinuxKMemCache *psCache)
+{
+    kmem_cache_destroy(psCache);
+}
+
+
+IMG_VOID *
+_KMemCacheAllocWrapper(LinuxKMemCache *psCache,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+                      gfp_t Flags,
+#else
+                      IMG_INT Flags,
+#endif
+                      IMG_CHAR *pszFileName,
+                      IMG_UINT32 ui32Line)
+{
+    IMG_VOID *pvRet;
+
+    pvRet = kmem_cache_alloc(psCache, Flags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+                           pvRet,
+                           pvRet,
+                           0,
+                           psCache,
+                           kmem_cache_size(psCache),
+                           pszFileName,
+                           ui32Line
+                           );
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+    return pvRet;
+}
+
+
+IMG_VOID
+_KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, pvObject, pszFileName, ui32Line);
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+    kmem_cache_free(psCache, pvObject);
+}
+
+
+const IMG_CHAR *
+KMemCacheNameWrapper(LinuxKMemCache *psCache)
+{
+    PVR_UNREFERENCED_PARAMETER(psCache);
+
+
+    return "";
+}
+
+
+LinuxMemArea *
+NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
+                   IMG_UINT32 ui32ByteOffset,
+                   IMG_UINT32 ui32Bytes)
+{
+    LinuxMemArea *psLinuxMemArea;
+
+    PVR_ASSERT((ui32ByteOffset+ui32Bytes) <= psParentLinuxMemArea->ui32ByteSize);
+
+    psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if(!psLinuxMemArea)
+    {
+        return NULL;
+    }
+
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_SUB_ALLOC;
+    psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea = psParentLinuxMemArea;
+    psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset = ui32ByteOffset;
+    psLinuxMemArea->ui32ByteSize = ui32Bytes;
+    psLinuxMemArea->ui32AreaFlags = psParentLinuxMemArea->ui32AreaFlags;
+    psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    {
+        DEBUG_LINUX_MEM_AREA_REC *psParentRecord;
+        psParentRecord = DebugLinuxMemAreaRecordFind(psParentLinuxMemArea);
+        DebugLinuxMemAreaRecordAdd(psLinuxMemArea, psParentRecord->ui32Flags);
+    }
+#endif
+
+    return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeSubLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+
+
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+static LinuxMemArea *
+LinuxMemAreaStructAlloc(IMG_VOID)
+{
+#if 0
+    LinuxMemArea *psLinuxMemArea;
+    psLinuxMemArea = kmem_cache_alloc(psLinuxMemAreaCache, GFP_KERNEL);
+    printk(KERN_ERR "%s: psLinuxMemArea=%p\n", __FUNCTION__, psLinuxMemArea);
+    dump_stack();
+    return psLinuxMemArea;
+#else
+    return KMemCacheAllocWrapper(psLinuxMemAreaCache, GFP_KERNEL);
+#endif
+}
+
+
+static IMG_VOID
+LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea)
+{
+    KMemCacheFreeWrapper(psLinuxMemAreaCache, psLinuxMemArea);
+
+
+}
+
+
+IMG_VOID
+LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea)
+{
+    switch(psLinuxMemArea->eAreaType)
+    {
+        case LINUX_MEM_AREA_VMALLOC:
+            FreeVMallocLinuxMemArea(psLinuxMemArea);
+            break;
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+            FreeAllocPagesLinuxMemArea(psLinuxMemArea);
+            break;
+        case LINUX_MEM_AREA_IOREMAP:
+            FreeIORemapLinuxMemArea(psLinuxMemArea);
+            break;
+	case LINUX_MEM_AREA_EXTERNAL_KV:
+	    FreeExternalKVLinuxMemArea(psLinuxMemArea);
+	    break;
+        case LINUX_MEM_AREA_IO:
+            FreeIOLinuxMemArea(psLinuxMemArea);
+            break;
+        case LINUX_MEM_AREA_SUB_ALLOC:
+            FreeSubLinuxMemArea(psLinuxMemArea);
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "%s: Unknown are type (%d)\n",
+                     __FUNCTION__, psLinuxMemArea->eAreaType));
+            break;
+    }
+}
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID
+DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psNewRecord;
+    const IMG_CHAR *pi8FlagsString;
+
+    mutex_lock(&g_sDebugMutex);
+
+    if(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        g_LinuxMemAreaWaterMark += psLinuxMemArea->ui32ByteSize;
+        if(g_LinuxMemAreaWaterMark > g_LinuxMemAreaHighWaterMark)
+        {
+            g_LinuxMemAreaHighWaterMark = g_LinuxMemAreaWaterMark;
+        }
+    }
+    g_LinuxMemAreaCount++;
+
+
+    psNewRecord = kmalloc(sizeof(DEBUG_LINUX_MEM_AREA_REC), GFP_KERNEL);
+    if(psNewRecord)
+    {
+
+        psNewRecord->psLinuxMemArea = psLinuxMemArea;
+        psNewRecord->ui32Flags = ui32Flags;
+        psNewRecord->pid = current->pid;
+
+		List_DEBUG_LINUX_MEM_AREA_REC_Insert(&g_LinuxMemAreaRecords, psNewRecord);
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+                 "%s: failed to allocate linux memory area record.",
+                 __FUNCTION__));
+    }
+
+
+    pi8FlagsString = HAPFlagsToString(ui32Flags);
+    if(strstr(pi8FlagsString, "UNKNOWN"))
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+                 "%s: Unexpected flags (0x%08lx) associated with psLinuxMemArea @ 0x%08lx",
+                 __FUNCTION__,
+                 ui32Flags,
+                 psLinuxMemArea));
+
+    }
+
+    mutex_unlock(&g_sDebugMutex);
+}
+
+
+
+IMG_VOID* MatchLinuxMemArea_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord,
+												va_list va)
+{
+	LinuxMemArea *psLinuxMemArea;
+
+	psLinuxMemArea = va_arg(va, LinuxMemArea*);
+	if(psCurrentRecord->psLinuxMemArea == psLinuxMemArea)
+	{
+		return psCurrentRecord;
+	}
+	else
+	{
+		return IMG_NULL;
+	}
+}
+
+
+static DEBUG_LINUX_MEM_AREA_REC *
+DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
+
+    mutex_lock(&g_sDebugMutex);
+	psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+														MatchLinuxMemArea_AnyVaCb,
+														psLinuxMemArea);
+
+    mutex_unlock(&g_sDebugMutex);
+
+    return psCurrentRecord;
+}
+
+
+static IMG_VOID
+DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
+
+    mutex_lock(&g_sDebugMutex);
+
+    if(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        g_LinuxMemAreaWaterMark -= psLinuxMemArea->ui32ByteSize;
+    }
+    g_LinuxMemAreaCount--;
+
+
+	psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+														MatchLinuxMemArea_AnyVaCb,
+														psLinuxMemArea);
+	if(psCurrentRecord)
+	{
+
+		List_DEBUG_LINUX_MEM_AREA_REC_Remove(psCurrentRecord);
+		kfree(psCurrentRecord);
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for psLinuxMemArea=%p\n",
+	     __FUNCTION__, psLinuxMemArea));
+	}
+
+    mutex_unlock(&g_sDebugMutex);
+}
+#endif
+
+
+IMG_VOID *
+LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea)
+{
+    switch(psLinuxMemArea->eAreaType)
+    {
+        case LINUX_MEM_AREA_VMALLOC:
+            return psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+        case LINUX_MEM_AREA_IOREMAP:
+            return psLinuxMemArea->uData.sIORemap.pvIORemapCookie;
+	case LINUX_MEM_AREA_EXTERNAL_KV:
+	    return psLinuxMemArea->uData.sExternalKV.pvExternalKV;
+        case LINUX_MEM_AREA_SUB_ALLOC:
+        {
+            IMG_CHAR *pAddr =
+                LinuxMemAreaToCpuVAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
+            if(!pAddr)
+            {
+                return NULL;
+            }
+            return pAddr + psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset;
+        }
+        default:
+            return NULL;
+    }
+}
+
+
+IMG_CPU_PHYADDR
+LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset)
+{
+    IMG_CPU_PHYADDR CpuPAddr;
+
+    CpuPAddr.uiAddr = 0;
+
+    switch(psLinuxMemArea->eAreaType)
+    {
+        case LINUX_MEM_AREA_IOREMAP:
+        {
+            CpuPAddr = psLinuxMemArea->uData.sIORemap.CPUPhysAddr;
+            CpuPAddr.uiAddr += ui32ByteOffset;
+            break;
+        }
+	case LINUX_MEM_AREA_EXTERNAL_KV:
+	{
+	    if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
+	    {
+		CpuPAddr = SysSysPAddrToCpuPAddr(psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr);
+		CpuPAddr.uiAddr += ui32ByteOffset;
+	    }
+	    else
+	    {
+		IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+		IMG_SYS_PHYADDR SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageIndex];
+
+		CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
+                CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+		if (0 == CpuPAddr.uiAddr) {
+			/* FIXME: REPLACE THIS WITH A DIFFERENT FIX SOMEDAY.
+			 * has only seen this code path be triggered when
+			 * DestroyOffsetStruct() calls this as a parameter for a debug
+			 * statement.  The times its been seen has been when the user-mode
+			 * program (i.e. X server) crashed when doing mode changes, or was
+			 * killed after an unhealthy mode change, and the kernel was trying
+			 * to clean up all of the VMA's associated with that client.  For
+			 * now, don't leave the address as 0 (which causes an Oops), but
+			 * work-around this by setting the CpuPAddr.uiAddr to 7.  As long
+			 * as 7 is used for a debug statement, it's no big deal.  If 7 were
+			 * used as a real address, an Oops would be caused anyway.
+			 */
+			printk(KERN_ERR "ERROR DESCRIPTION TO FOLLOW:\n");
+			printk(KERN_ERR "  LinuxMemAreaToCpuPAddr() failed to look up a "
+				"physical\n  address of a memory mapped area (i.e. got an "
+				"address\n  of 0x00000000).  If this occured after increasing "
+				"the\n  resolution of a display, it probably indicates that "
+				"the\n  client stepped past the end of the old frame buffer's\n"
+				"  memory, and needed to re-initialize its connection with\n"
+				"  PVR services in order to map the new frame buffer address."
+				"\n\n");
+			CpuPAddr.uiAddr = 7;
+		}
+	    }
+            break;
+	}
+        case LINUX_MEM_AREA_IO:
+        {
+            CpuPAddr = psLinuxMemArea->uData.sIO.CPUPhysAddr;
+            CpuPAddr.uiAddr += ui32ByteOffset;
+            break;
+        }
+        case LINUX_MEM_AREA_VMALLOC:
+        {
+            IMG_CHAR *pCpuVAddr;
+            pCpuVAddr =
+                (IMG_CHAR *)psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+            pCpuVAddr += ui32ByteOffset;
+            CpuPAddr.uiAddr = VMallocToPhys(pCpuVAddr);
+            break;
+        }
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+        {
+            struct page *page;
+            IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+            page = psLinuxMemArea->uData.sPageList.pvPageList[ui32PageIndex];
+            CpuPAddr.uiAddr = page_to_phys(page);
+            CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+            break;
+        }
+        case LINUX_MEM_AREA_SUB_ALLOC:
+        {
+            CpuPAddr =
+                OSMemHandleToCpuPAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
+                                      psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset
+                                        + ui32ByteOffset);
+            break;
+        }
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
+                     __FUNCTION__, psLinuxMemArea->eAreaType));
+            break;
+   }
+
+    PVR_ASSERT(CpuPAddr.uiAddr);
+    return CpuPAddr;
+}
+
+
+IMG_BOOL
+LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea)
+{
+    switch(psLinuxMemArea->eAreaType)
+    {
+        case LINUX_MEM_AREA_IOREMAP:
+        case LINUX_MEM_AREA_IO:
+            return IMG_TRUE;
+
+	case LINUX_MEM_AREA_EXTERNAL_KV:
+	    return psLinuxMemArea->uData.sExternalKV.bPhysContig;
+
+        case LINUX_MEM_AREA_VMALLOC:
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+	    return IMG_FALSE;
+
+        case LINUX_MEM_AREA_SUB_ALLOC:
+
+	    return LinuxMemAreaPhysIsContig(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
+
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
+                     __FUNCTION__, psLinuxMemArea->eAreaType));
+	    break;
+    }
+    return IMG_FALSE;
+}
+
+
+const IMG_CHAR *
+LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType)
+{
+
+    switch(eMemAreaType)
+    {
+        case LINUX_MEM_AREA_IOREMAP:
+            return "LINUX_MEM_AREA_IOREMAP";
+	case LINUX_MEM_AREA_EXTERNAL_KV:
+	    return "LINUX_MEM_AREA_EXTERNAL_KV";
+        case LINUX_MEM_AREA_IO:
+            return "LINUX_MEM_AREA_IO";
+        case LINUX_MEM_AREA_VMALLOC:
+            return "LINUX_MEM_AREA_VMALLOC";
+        case LINUX_MEM_AREA_SUB_ALLOC:
+            return "LINUX_MEM_AREA_SUB_ALLOC";
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+            return "LINUX_MEM_AREA_ALLOC_PAGES";
+        default:
+            PVR_ASSERT(0);
+    }
+
+    return "";
+}
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static void ProcSeqStartstopDebugMutex(struct seq_file *sfile, IMG_BOOL start)
+{
+	if(start)
+	{
+	    mutex_lock(&g_sDebugMutex);
+	}
+	else
+	{
+	    mutex_unlock(&g_sDebugMutex);
+	}
+}
+#endif
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+
+IMG_VOID* DecOffMemAreaRec_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psNode, va_list va)
+{
+	off_t *pOff = va_arg(va, off_t*);
+	if (--(*pOff))
+	{
+		return IMG_NULL;
+	}
+	else
+	{
+		return psNode;
+	}
+}
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psRecord;
+	psRecord = (DEBUG_LINUX_MEM_AREA_REC*)
+				List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+													DecOffMemAreaRec_AnyVaCb,
+													&off);
+	return (void*)psRecord;
+}
+
+static void* ProcSeqOff2ElementMemArea(struct seq_file * sfile, loff_t off)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psRecord;
+	if(!off)
+	{
+		return PVR_PROC_SEQ_START_TOKEN;
+	}
+
+	psRecord = (DEBUG_LINUX_MEM_AREA_REC*)
+				List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+													DecOffMemAreaRec_AnyVaCb,
+													&off);
+	return (void*)psRecord;
+}
+
+
+static void ProcSeqShowMemArea(struct seq_file *sfile,void* el)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psRecord = (DEBUG_LINUX_MEM_AREA_REC*)el;
+	if(el == PVR_PROC_SEQ_START_TOKEN)
+	{
+
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+        seq_printf( sfile,
+			  "Number of Linux Memory Areas: %lu\n"
+                          "At the current water mark these areas correspond to %lu bytes (excluding SUB areas)\n"
+                          "At the highest water mark these areas corresponded to %lu bytes (excluding SUB areas)\n"
+                          "\nDetails for all Linux Memory Areas:\n"
+                          "%s %-24s %s %s %-8s %-5s %s\n",
+                          g_LinuxMemAreaCount,
+                          g_LinuxMemAreaWaterMark,
+                          g_LinuxMemAreaHighWaterMark,
+                          "psLinuxMemArea",
+                          "LinuxMemType",
+                          "CpuVAddr",
+                          "CpuPAddr",
+                          "Bytes",
+                          "Pid",
+                          "Flags"
+                         );
+#else
+        seq_printf( sfile,
+                          "<mem_areas_header>\n"
+                          "\t<count>%lu</count>\n"
+                          "\t<watermark key=\"mar0\" description=\"current\" bytes=\"%lu\"/>\n"
+                          "\t<watermark key=\"mar1\" description=\"high\" bytes=\"%lu\"/>\n"
+                          "</mem_areas_header>\n",
+                          g_LinuxMemAreaCount,
+                          g_LinuxMemAreaWaterMark,
+                          g_LinuxMemAreaHighWaterMark
+                         );
+#endif
+		return;
+	}
+
+        seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                       "%8p       %-24s %8p %08lx %-8ld %-5u %08lx=(%s)\n",
+#else
+                       "<linux_mem_area>\n"
+                       "\t<pointer>%8p</pointer>\n"
+                       "\t<type>%s</type>\n"
+                       "\t<cpu_virtual>%8p</cpu_virtual>\n"
+                       "\t<cpu_physical>%08lx</cpu_physical>\n"
+                       "\t<bytes>%ld</bytes>\n"
+                       "\t<pid>%u</pid>\n"
+                       "\t<flags>%08lx</flags>\n"
+                       "\t<flags_string>%s</flags_string>\n"
+                       "</linux_mem_area>\n",
+#endif
+                       psRecord->psLinuxMemArea,
+                       LinuxMemAreaTypeToString(psRecord->psLinuxMemArea->eAreaType),
+                       LinuxMemAreaToCpuVAddr(psRecord->psLinuxMemArea),
+                       LinuxMemAreaToCpuPAddr(psRecord->psLinuxMemArea,0).uiAddr,
+                       psRecord->psLinuxMemArea->ui32ByteSize,
+                       psRecord->pid,
+                       psRecord->ui32Flags,
+                       HAPFlagsToString(psRecord->ui32Flags)
+                      );
+
+}
+
+#else
+
+static off_t
+printLinuxMemAreaRecords(IMG_CHAR * buffer, size_t count, off_t off)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psRecord;
+    off_t Ret;
+
+    mutex_lock(&g_sDebugMutex);
+
+    if(!off)
+    {
+        if(count < 500)
+        {
+            Ret = 0;
+            goto unlock_and_return;
+        }
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+        Ret = printAppend(buffer, count, 0,
+                          "Number of Linux Memory Areas: %lu\n"
+                          "At the current water mark these areas correspond to %lu bytes (excluding SUB areas)\n"
+                          "At the highest water mark these areas corresponded to %lu bytes (excluding SUB areas)\n"
+                          "\nDetails for all Linux Memory Areas:\n"
+                          "%s %-24s %s %s %-8s %-5s %s\n",
+                          g_LinuxMemAreaCount,
+                          g_LinuxMemAreaWaterMark,
+                          g_LinuxMemAreaHighWaterMark,
+                          "psLinuxMemArea",
+                          "LinuxMemType",
+                          "CpuVAddr",
+                          "CpuPAddr",
+                          "Bytes",
+                          "Pid",
+                          "Flags"
+                         );
+#else
+        Ret = printAppend(buffer, count, 0,
+                          "<mem_areas_header>\n"
+                          "\t<count>%lu</count>\n"
+                          "\t<watermark key=\"mar0\" description=\"current\" bytes=\"%lu\"/>\n"
+                          "\t<watermark key=\"mar1\" description=\"high\" bytes=\"%lu\"/>\n"
+                          "</mem_areas_header>\n",
+                          g_LinuxMemAreaCount,
+                          g_LinuxMemAreaWaterMark,
+                          g_LinuxMemAreaHighWaterMark
+                         );
+#endif
+        goto unlock_and_return;
+    }
+
+	psRecord = (DEBUG_LINUX_MEM_AREA_REC*)
+				List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+													DecOffMemAreaRec_AnyVaCb,
+													&off);
+
+    if(!psRecord)
+    {
+        Ret = END_OF_FILE;
+        goto unlock_and_return;
+    }
+
+    if(count < 500)
+    {
+        Ret = 0;
+        goto unlock_and_return;
+    }
+
+    Ret =  printAppend(buffer, count, 0,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                       "%8p       %-24s %8p %08lx %-8ld %-5u %08lx=(%s)\n",
+#else
+                       "<linux_mem_area>\n"
+                       "\t<pointer>%8p</pointer>\n"
+                       "\t<type>%s</type>\n"
+                       "\t<cpu_virtual>%8p</cpu_virtual>\n"
+                       "\t<cpu_physical>%08lx</cpu_physical>\n"
+                       "\t<bytes>%ld</bytes>\n"
+                       "\t<pid>%u</pid>\n"
+                       "\t<flags>%08lx</flags>\n"
+                       "\t<flags_string>%s</flags_string>\n"
+                       "</linux_mem_area>\n",
+#endif
+                       psRecord->psLinuxMemArea,
+                       LinuxMemAreaTypeToString(psRecord->psLinuxMemArea->eAreaType),
+                       LinuxMemAreaToCpuVAddr(psRecord->psLinuxMemArea),
+                       LinuxMemAreaToCpuPAddr(psRecord->psLinuxMemArea,0).uiAddr,
+                       psRecord->psLinuxMemArea->ui32ByteSize,
+                       psRecord->pid,
+                       psRecord->ui32Flags,
+                       HAPFlagsToString(psRecord->ui32Flags)
+                      );
+
+unlock_and_return:
+    mutex_unlock(&g_sDebugMutex);
+    return Ret;
+}
+#endif
+
+#endif
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+
+IMG_VOID* DecOffMemAllocRec_AnyVaCb(DEBUG_MEM_ALLOC_REC *psNode, va_list va)
+{
+	off_t *pOff = va_arg(va, off_t*);
+	if (--(*pOff))
+	{
+		return IMG_NULL;
+	}
+	else
+	{
+		return psNode;
+	}
+}
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off)
+{
+    DEBUG_MEM_ALLOC_REC *psRecord;
+	psRecord = (DEBUG_MEM_ALLOC_REC*)
+		List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords,
+										DecOffMemAllocRec_AnyVaCb,
+										&off);
+#if defined(DEBUG_LINUX_XML_PROC_FILES)
+	if(!psRecord)
+	{
+		seq_printf( sfile, "</meminfo>\n");
+	}
+#endif
+
+	return (void*)psRecord;
+}
+
+static void* ProcSeqOff2ElementMemoryRecords(struct seq_file *sfile, loff_t off)
+{
+    DEBUG_MEM_ALLOC_REC *psRecord;
+	if(!off)
+	{
+		return PVR_PROC_SEQ_START_TOKEN;
+	}
+
+	psRecord = (DEBUG_MEM_ALLOC_REC*)
+		List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords,
+										DecOffMemAllocRec_AnyVaCb,
+										&off);
+
+#if defined(DEBUG_LINUX_XML_PROC_FILES)
+	if(!psRecord)
+	{
+		seq_printf( sfile, "</meminfo>\n");
+	}
+#endif
+
+	return (void*)psRecord;
+}
+
+static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el)
+{
+    DEBUG_MEM_ALLOC_REC *psRecord = (DEBUG_MEM_ALLOC_REC*)el;
+	if(el == PVR_PROC_SEQ_START_TOKEN)
+	{
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+
+        seq_printf( sfile, "%-60s: %ld bytes\n",
+                           "Current Water Mark of bytes allocated via kmalloc",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+        seq_printf( sfile, "%-60s: %ld bytes\n",
+                           "Highest Water Mark of bytes allocated via kmalloc",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+        seq_printf( sfile, "%-60s: %ld bytes\n",
+                           "Current Water Mark of bytes allocated via vmalloc",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+        seq_printf( sfile, "%-60s: %ld bytes\n",
+                           "Highest Water Mark of bytes allocated via vmalloc",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+        seq_printf( sfile, "%-60s: %ld bytes\n",
+                           "Current Water Mark of bytes allocated via alloc_pages",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+        seq_printf( sfile, "%-60s: %ld bytes\n",
+                           "Highest Water Mark of bytes allocated via alloc_pages",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+        seq_printf( sfile, "%-60s: %ld bytes\n",
+                           "Current Water Mark of bytes allocated via ioremap",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+        seq_printf( sfile, "%-60s: %ld bytes\n",
+                           "Highest Water Mark of bytes allocated via ioremap",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+        seq_printf( sfile, "%-60s: %ld bytes\n",
+                           "Current Water Mark of bytes reserved for \"IO\" memory areas",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+        seq_printf( sfile, "%-60s: %ld bytes\n",
+                           "Highest Water Mark of bytes allocated for \"IO\" memory areas",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+        seq_printf( sfile, "%-60s: %ld bytes\n",
+                           "Current Water Mark of bytes allocated via kmem_cache_alloc",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+        seq_printf( sfile, "%-60s: %ld bytes\n",
+                           "Highest Water Mark of bytes allocated via kmem_cache_alloc",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+        seq_printf( sfile, "\n");
+
+        seq_printf( sfile, "%-60s: %ld bytes\n",
+                           "The Current Water Mark for memory allocated from system RAM",
+                           g_SysRAMWaterMark);
+        seq_printf( sfile, "%-60s: %ld bytes\n",
+                           "The Highest Water Mark for memory allocated from system RAM",
+                           g_SysRAMHighWaterMark);
+        seq_printf( sfile, "%-60s: %ld bytes\n",
+                           "The Current Water Mark for memory allocated from IO memory",
+                           g_IOMemWaterMark);
+        seq_printf( sfile, "%-60s: %ld bytes\n",
+                           "The Highest Water Mark for memory allocated from IO memory",
+                           g_IOMemHighWaterMark);
+
+        seq_printf( sfile, "\n");
+
+		seq_printf( sfile, "Details for all known allocations:\n"
+                           "%-16s %-8s %-8s %-10s %-5s %-10s %s\n",
+                           "Type",
+                           "CpuVAddr",
+                           "CpuPAddr",
+                           "Bytes",
+                           "PID",
+                           "PrivateData",
+                           "Filename:Line");
+
+#else
+
+
+		seq_printf( sfile, "<meminfo>\n<meminfo_header>\n");
+		seq_printf( sfile,
+                           "<watermark key=\"mr0\" description=\"kmalloc_current\" bytes=\"%ld\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+		seq_printf( sfile,
+                           "<watermark key=\"mr1\" description=\"kmalloc_high\" bytes=\"%ld\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+		seq_printf( sfile,
+                           "<watermark key=\"mr2\" description=\"vmalloc_current\" bytes=\"%ld\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+		seq_printf( sfile,
+                           "<watermark key=\"mr3\" description=\"vmalloc_high\" bytes=\"%ld\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+		seq_printf( sfile,
+                           "<watermark key=\"mr4\" description=\"alloc_pages_current\" bytes=\"%ld\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+		seq_printf( sfile,
+                           "<watermark key=\"mr5\" description=\"alloc_pages_high\" bytes=\"%ld\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+		seq_printf( sfile,
+                           "<watermark key=\"mr6\" description=\"ioremap_current\" bytes=\"%ld\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+		seq_printf( sfile,
+                           "<watermark key=\"mr7\" description=\"ioremap_high\" bytes=\"%ld\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+		seq_printf( sfile,
+                           "<watermark key=\"mr8\" description=\"io_current\" bytes=\"%ld\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+		seq_printf( sfile,
+                           "<watermark key=\"mr9\" description=\"io_high\" bytes=\"%ld\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+		seq_printf( sfile,
+                           "<watermark key=\"mr10\" description=\"kmem_cache_current\" bytes=\"%ld\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+		seq_printf( sfile,
+                           "<watermark key=\"mr11\" description=\"kmem_cache_high\" bytes=\"%ld\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+		seq_printf( sfile,"\n" );
+
+		seq_printf( sfile,
+                           "<watermark key=\"mr14\" description=\"system_ram_current\" bytes=\"%ld\"/>\n",
+                           g_SysRAMWaterMark);
+		seq_printf( sfile,
+                           "<watermark key=\"mr15\" description=\"system_ram_high\" bytes=\"%ld\"/>\n",
+                           g_SysRAMHighWaterMark);
+		seq_printf( sfile,
+                           "<watermark key=\"mr16\" description=\"system_io_current\" bytes=\"%ld\"/>\n",
+                           g_IOMemWaterMark);
+		seq_printf( sfile,
+                           "<watermark key=\"mr17\" description=\"system_io_high\" bytes=\"%ld\"/>\n",
+                           g_IOMemHighWaterMark);
+
+		seq_printf( sfile, "</meminfo_header>\n");
+
+#endif
+		return;
+	}
+
+    if(psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+    {
+		seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                           "%-16s %-8p %08lx %-10ld %-5d %-10s %s:%ld\n",
+#else
+                           "<allocation>\n"
+                           "\t<type>%s</type>\n"
+                           "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+                           "\t<cpu_physical>%08lx</cpu_physical>\n"
+                           "\t<bytes>%ld</bytes>\n"
+                           "\t<pid>%d</pid>\n"
+                           "\t<private>%s</private>\n"
+                           "\t<filename>%s</filename>\n"
+                           "\t<line>%ld</line>\n"
+                           "</allocation>\n",
+#endif
+                           DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+                           psRecord->pvCpuVAddr,
+                           psRecord->ulCpuPAddr,
+                           psRecord->ui32Bytes,
+                           psRecord->pid,
+                           "NULL",
+                           psRecord->pszFileName,
+                           psRecord->ui32Line);
+    }
+    else
+    {
+		seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                           "%-16s %-8p %08lx %-10ld %-5d %-10s %s:%ld\n",
+#else
+                           "<allocation>\n"
+                           "\t<type>%s</type>\n"
+                           "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+                           "\t<cpu_physical>%08lx</cpu_physical>\n"
+                           "\t<bytes>%ld</bytes>\n"
+                           "\t<pid>%d</pid>\n"
+                           "\t<private>%s</private>\n"
+                           "\t<filename>%s</filename>\n"
+                           "\t<line>%ld</line>\n"
+                           "</allocation>\n",
+#endif
+                           DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+                           psRecord->pvCpuVAddr,
+                           psRecord->ulCpuPAddr,
+                           psRecord->ui32Bytes,
+                           psRecord->pid,
+                           KMemCacheNameWrapper(psRecord->pvPrivateData),
+                           psRecord->pszFileName,
+                           psRecord->ui32Line);
+    }
+}
+
+
+
+#else
+
+static off_t
+printMemoryRecords(IMG_CHAR * buffer, size_t count, off_t off)
+{
+    DEBUG_MEM_ALLOC_REC *psRecord;
+    off_t Ret;
+
+    mutex_lock(&g_sDebugMutex);
+
+    if(!off)
+    {
+        if(count < 1000)
+        {
+            Ret = 0;
+            goto unlock_and_return;
+        }
+
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+
+        Ret =  printAppend(buffer, count, 0, "%-60s: %ld bytes\n",
+                           "Current Water Mark of bytes allocated via kmalloc",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+        Ret =  printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                           "Highest Water Mark of bytes allocated via kmalloc",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+        Ret =  printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                           "Current Water Mark of bytes allocated via vmalloc",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+        Ret =  printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                           "Highest Water Mark of bytes allocated via vmalloc",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+        Ret =  printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                           "Current Water Mark of bytes allocated via alloc_pages",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+        Ret =  printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                           "Highest Water Mark of bytes allocated via alloc_pages",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+        Ret =  printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                           "Current Water Mark of bytes allocated via ioremap",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+        Ret =  printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                           "Highest Water Mark of bytes allocated via ioremap",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+        Ret =  printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                           "Current Water Mark of bytes reserved for \"IO\" memory areas",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+        Ret =  printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                           "Highest Water Mark of bytes allocated for \"IO\" memory areas",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+        Ret =  printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                           "Current Water Mark of bytes allocated via kmem_cache_alloc",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+        Ret =  printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                           "Highest Water Mark of bytes allocated via kmem_cache_alloc",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+        Ret =  printAppend(buffer, count, Ret, "\n");
+
+        Ret =  printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                           "The Current Water Mark for memory allocated from system RAM",
+                           g_SysRAMWaterMark);
+        Ret =  printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                           "The Highest Water Mark for memory allocated from system RAM",
+                           g_SysRAMHighWaterMark);
+        Ret =  printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                           "The Current Water Mark for memory allocated from IO memory",
+                           g_IOMemWaterMark);
+        Ret =  printAppend(buffer, count, Ret, "%-60s: %ld bytes\n",
+                           "The Highest Water Mark for memory allocated from IO memory",
+                           g_IOMemHighWaterMark);
+
+        Ret =  printAppend(buffer, count, Ret, "\n");
+
+        Ret =  printAppend(buffer, count, Ret, "Details for all known allocations:\n"
+                           "%-16s %-8s %-8s %-10s %-5s %-10s %s\n",
+                           "Type",
+                           "CpuVAddr",
+                           "CpuPAddr",
+                           "Bytes",
+                           "PID",
+                           "PrivateData",
+                           "Filename:Line");
+
+#else
+
+
+        Ret =  printAppend(buffer, count, 0, "<meminfo>\n<meminfo_header>\n");
+        Ret =  printAppend(buffer, count, Ret,
+                           "<watermark key=\"mr0\" description=\"kmalloc_current\" bytes=\"%ld\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+        Ret =  printAppend(buffer, count, Ret,
+                           "<watermark key=\"mr1\" description=\"kmalloc_high\" bytes=\"%ld\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+        Ret =  printAppend(buffer, count, Ret,
+                           "<watermark key=\"mr2\" description=\"vmalloc_current\" bytes=\"%ld\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+        Ret =  printAppend(buffer, count, Ret,
+                           "<watermark key=\"mr3\" description=\"vmalloc_high\" bytes=\"%ld\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+        Ret =  printAppend(buffer, count, Ret,
+                           "<watermark key=\"mr4\" description=\"alloc_pages_current\" bytes=\"%ld\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+        Ret =  printAppend(buffer, count, Ret,
+                           "<watermark key=\"mr5\" description=\"alloc_pages_high\" bytes=\"%ld\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+        Ret =  printAppend(buffer, count, Ret,
+                           "<watermark key=\"mr6\" description=\"ioremap_current\" bytes=\"%ld\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+        Ret =  printAppend(buffer, count, Ret,
+                           "<watermark key=\"mr7\" description=\"ioremap_high\" bytes=\"%ld\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+        Ret =  printAppend(buffer, count, Ret,
+                           "<watermark key=\"mr8\" description=\"io_current\" bytes=\"%ld\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+        Ret =  printAppend(buffer, count, Ret,
+                           "<watermark key=\"mr9\" description=\"io_high\" bytes=\"%ld\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+        Ret =  printAppend(buffer, count, Ret,
+                           "<watermark key=\"mr10\" description=\"kmem_cache_current\" bytes=\"%ld\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+        Ret =  printAppend(buffer, count, Ret,
+                           "<watermark key=\"mr11\" description=\"kmem_cache_high\" bytes=\"%ld\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+        Ret =  printAppend(buffer, count, Ret, "\n");
+
+        Ret =  printAppend(buffer, count, Ret,
+                           "<watermark key=\"mr14\" description=\"system_ram_current\" bytes=\"%ld\"/>\n",
+                           g_SysRAMWaterMark);
+        Ret =  printAppend(buffer, count, Ret,
+                           "<watermark key=\"mr15\" description=\"system_ram_high\" bytes=\"%ld\"/>\n",
+                           g_SysRAMHighWaterMark);
+        Ret =  printAppend(buffer, count, Ret,
+                           "<watermark key=\"mr16\" description=\"system_io_current\" bytes=\"%ld\"/>\n",
+                           g_IOMemWaterMark);
+        Ret =  printAppend(buffer, count, Ret,
+                           "<watermark key=\"mr17\" description=\"system_io_high\" bytes=\"%ld\"/>\n",
+                           g_IOMemHighWaterMark);
+
+        Ret =  printAppend(buffer, count, Ret, "</meminfo_header>\n");
+
+#endif
+
+        goto unlock_and_return;
+    }
+
+    if(count < 1000)
+    {
+        Ret = 0;
+        goto unlock_and_return;
+    }
+
+	psRecord = (DEBUG_MEM_ALLOC_REC*)
+		List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords,
+										DecOffMemAllocRec_AnyVaCb,
+										&off);
+    if(!psRecord)
+    {
+#if defined(DEBUG_LINUX_XML_PROC_FILES)
+		if(off == 0)
+		{
+			Ret =  printAppend(buffer, count, 0, "</meminfo>\n");
+			goto unlock_and_return;
+		}
+#endif
+        Ret = END_OF_FILE;
+        goto unlock_and_return;
+    }
+
+    if(psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+    {
+        Ret =  printAppend(buffer, count, 0,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                           "%-16s %-8p %08lx %-10ld %-5d %-10s %s:%ld\n",
+#else
+                           "<allocation>\n"
+                           "\t<type>%s</type>\n"
+                           "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+                           "\t<cpu_physical>%08lx</cpu_physical>\n"
+                           "\t<bytes>%ld</bytes>\n"
+                           "\t<pid>%d</pid>\n"
+                           "\t<private>%s</private>\n"
+                           "\t<filename>%s</filename>\n"
+                           "\t<line>%ld</line>\n"
+                           "</allocation>\n",
+#endif
+                           DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+                           psRecord->pvCpuVAddr,
+                           psRecord->ulCpuPAddr,
+                           psRecord->ui32Bytes,
+                           psRecord->pid,
+                           "NULL",
+                           psRecord->pszFileName,
+                           psRecord->ui32Line);
+    }
+    else
+    {
+        Ret =  printAppend(buffer, count, 0,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                           "%-16s %-8p %08lx %-10ld %-5d %-10s %s:%ld\n",
+#else
+                           "<allocation>\n"
+                           "\t<type>%s</type>\n"
+                           "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+                           "\t<cpu_physical>%08lx</cpu_physical>\n"
+                           "\t<bytes>%ld</bytes>\n"
+                           "\t<pid>%d</pid>\n"
+                           "\t<private>%s</private>\n"
+                           "\t<filename>%s</filename>\n"
+                           "\t<line>%ld</line>\n"
+                           "</allocation>\n",
+#endif
+                           DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+                           psRecord->pvCpuVAddr,
+                           psRecord->ulCpuPAddr,
+                           psRecord->ui32Bytes,
+                           psRecord->pid,
+                           KMemCacheNameWrapper(psRecord->pvPrivateData),
+                           psRecord->pszFileName,
+                           psRecord->ui32Line);
+    }
+
+unlock_and_return:
+    mutex_unlock(&g_sDebugMutex);
+    return Ret;
+}
+#endif
+#endif
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MMAP_AREAS)
+const IMG_CHAR *
+HAPFlagsToString(IMG_UINT32 ui32Flags)
+{
+    static IMG_CHAR szFlags[50];
+    IMG_INT32 i32Pos = 0;
+    IMG_UINT32 ui32CacheTypeIndex, ui32MapTypeIndex;
+    IMG_CHAR *apszCacheTypes[] = {
+        "UNCACHED",
+        "CACHED",
+        "WRITECOMBINE",
+        "UNKNOWN"
+    };
+    IMG_CHAR *apszMapType[] = {
+        "KERNEL_ONLY",
+        "SINGLE_PROCESS",
+        "MULTI_PROCESS",
+        "FROM_EXISTING_PROCESS",
+        "NO_CPU_VIRTUAL",
+        "UNKNOWN"
+    };
+
+
+    if(ui32Flags & PVRSRV_HAP_UNCACHED){
+        ui32CacheTypeIndex=0;
+    }else if(ui32Flags & PVRSRV_HAP_CACHED){
+        ui32CacheTypeIndex=1;
+    }else if(ui32Flags & PVRSRV_HAP_WRITECOMBINE){
+        ui32CacheTypeIndex=2;
+    }else{
+        ui32CacheTypeIndex=3;
+        PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type (%u)",
+                 __FUNCTION__, (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)));
+    }
+
+
+    if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY){
+        ui32MapTypeIndex = 0;
+    }else if(ui32Flags & PVRSRV_HAP_SINGLE_PROCESS){
+        ui32MapTypeIndex = 1;
+    }else if(ui32Flags & PVRSRV_HAP_MULTI_PROCESS){
+        ui32MapTypeIndex = 2;
+    }else if(ui32Flags & PVRSRV_HAP_FROM_EXISTING_PROCESS){
+        ui32MapTypeIndex = 3;
+    }else if(ui32Flags & PVRSRV_HAP_NO_CPU_VIRTUAL){
+        ui32MapTypeIndex = 4;
+    }else{
+        ui32MapTypeIndex = 5;
+        PVR_DPF((PVR_DBG_ERROR, "%s: unknown map type (%u)",
+                 __FUNCTION__, (ui32Flags & PVRSRV_HAP_MAPTYPE_MASK)));
+    }
+
+    i32Pos = sprintf(szFlags, "%s|", apszCacheTypes[ui32CacheTypeIndex]);
+    if (i32Pos <= 0)
+    {
+	PVR_DPF((PVR_DBG_ERROR, "%s: sprintf for cache type %u failed (%d)",
+		__FUNCTION__, ui32CacheTypeIndex, i32Pos));
+	szFlags[0] = 0;
+    }
+    else
+    {
+        sprintf(szFlags + i32Pos, "%s", apszMapType[ui32MapTypeIndex]);
+    }
+
+    return szFlags;
+}
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mm.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mm.h
new file mode 100644
index 0000000..78f3d14
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mm.h
@@ -0,0 +1,323 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __IMG_LINUX_MM_H__
+#define __IMG_LINUX_MM_H__
+
+#include <linux/version.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#include <asm/io.h>
+
+#define	PHYS_TO_PFN(phys) ((phys) >> PAGE_SHIFT)
+#define PFN_TO_PHYS(pfn) ((pfn) << PAGE_SHIFT)
+
+#define RANGE_TO_PAGES(range) (((range) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
+
+#define	ADDR_TO_PAGE_OFFSET(addr) (((unsigned long)(addr)) & (PAGE_SIZE - 1))
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10))
+#define	REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_pfn_range(vma, addr, pfn, size, prot)
+#else
+#define	REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_page_range(vma, addr, PFN_TO_PHYS(pfn), size, prot)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
+#define	IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) io_remap_pfn_range(vma, addr, pfn, size, prot)
+#else
+#define	IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) io_remap_page_range(vma, addr, PFN_TO_PHYS(pfn), size, prot)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#define	VM_INSERT_PAGE(vma, addr, page) vm_insert_page(vma, addr, page)
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10))
+#define VM_INSERT_PAGE(vma, addr, page) remap_pfn_range(vma, addr, page_to_pfn(page), PAGE_SIZE, vma->vm_page_prot);
+#else
+#define VM_INSERT_PAGE(vma, addr, page) remap_page_range(vma, addr, page_to_phys(page), PAGE_SIZE, vma->vm_page_prot);
+#endif
+#endif
+
+static inline IMG_UINT32 VMallocToPhys(IMG_VOID *pCpuVAddr)
+{
+	return (page_to_phys(vmalloc_to_page(pCpuVAddr)) + ADDR_TO_PAGE_OFFSET(pCpuVAddr));
+
+}
+
+typedef enum {
+    LINUX_MEM_AREA_IOREMAP,
+	LINUX_MEM_AREA_EXTERNAL_KV,
+    LINUX_MEM_AREA_IO,
+    LINUX_MEM_AREA_VMALLOC,
+    LINUX_MEM_AREA_ALLOC_PAGES,
+    LINUX_MEM_AREA_SUB_ALLOC,
+    LINUX_MEM_AREA_TYPE_COUNT
+}LINUX_MEM_AREA_TYPE;
+
+typedef struct _LinuxMemArea LinuxMemArea;
+
+
+struct _LinuxMemArea {
+    LINUX_MEM_AREA_TYPE eAreaType;
+    union _uData
+    {
+        struct _sIORemap
+        {
+
+            IMG_CPU_PHYADDR CPUPhysAddr;
+            IMG_VOID *pvIORemapCookie;
+        }sIORemap;
+        struct _sExternalKV
+        {
+
+	    IMG_BOOL bPhysContig;
+	    union {
+
+		    IMG_SYS_PHYADDR SysPhysAddr;
+		    IMG_SYS_PHYADDR *pSysPhysAddr;
+	    } uPhysAddr;
+            IMG_VOID *pvExternalKV;
+        }sExternalKV;
+        struct _sIO
+        {
+
+            IMG_CPU_PHYADDR CPUPhysAddr;
+        }sIO;
+        struct _sVmalloc
+        {
+
+            IMG_VOID *pvVmallocAddress;
+        }sVmalloc;
+        struct _sPageList
+        {
+
+            struct page **pvPageList;
+	    IMG_HANDLE hBlockPageList;
+        }sPageList;
+        struct _sSubAlloc
+        {
+
+            LinuxMemArea *psParentLinuxMemArea;
+            IMG_UINT32 ui32ByteOffset;
+        }sSubAlloc;
+    }uData;
+
+    IMG_UINT32 ui32ByteSize;
+
+    IMG_UINT32 ui32AreaFlags;
+
+    IMG_BOOL bMMapRegistered;
+
+
+    struct list_head	sMMapItem;
+
+
+    struct list_head	sMMapOffsetStructList;
+};
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
+typedef kmem_cache_t LinuxKMemCache;
+#else
+typedef struct kmem_cache LinuxKMemCache;
+#endif
+
+
+PVRSRV_ERROR LinuxMMInit(IMG_VOID);
+
+
+IMG_VOID LinuxMMCleanup(IMG_VOID);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMallocWrapper(ui32ByteSize) _KMallocWrapper(ui32ByteSize, __FILE__, __LINE__)
+#else
+#define KMallocWrapper(ui32ByteSize) _KMallocWrapper(ui32ByteSize, NULL, 0)
+#endif
+IMG_VOID *_KMallocWrapper(IMG_UINT32 ui32ByteSize, IMG_CHAR *szFileName, IMG_UINT32 ui32Line);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, NULL, 0)
+#endif
+IMG_VOID _KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, __FILE__, __LINE__)
+#else
+#define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, NULL, 0)
+#endif
+IMG_VOID *_VMallocWrapper(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, NULL, 0)
+#endif
+IMG_VOID _VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+LinuxMemArea *NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
+    _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, __FILE__, __LINE__)
+#else
+#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
+    _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, NULL, 0)
+#endif
+IMG_VOID *_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
+                          IMG_UINT32 ui32Bytes,
+                          IMG_UINT32 ui32MappingFlags,
+                          IMG_CHAR *pszFileName,
+                          IMG_UINT32 ui32Line);
+
+
+LinuxMemArea *NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define IOUnmapWrapper(pvIORemapCookie) \
+    _IOUnmapWrapper(pvIORemapCookie, __FILE__, __LINE__)
+#else
+#define IOUnmapWrapper(pvIORemapCookie) \
+    _IOUnmapWrapper(pvIORemapCookie, NULL, 0)
+#endif
+IMG_VOID _IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+struct page *LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
+
+
+LinuxKMemCache *KMemCacheCreateWrapper(IMG_CHAR *pszName, size_t Size, size_t Align, IMG_UINT32 ui32Flags);
+
+
+IMG_VOID KMemCacheDestroyWrapper(LinuxKMemCache *psCache);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, __FILE__, __LINE__)
+#else
+#define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, NULL, 0)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, gfp_t Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+#else
+IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, int Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, __FILE__, __LINE__)
+#else
+#define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, NULL, 0)
+#endif
+IMG_VOID _KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+const IMG_CHAR *KMemCacheNameWrapper(LinuxKMemCache *psCache);
+
+
+LinuxMemArea *NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+LinuxMemArea *NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+LinuxMemArea *NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
+                                 IMG_UINT32 ui32ByteOffset,
+                                 IMG_UINT32 ui32Bytes);
+
+
+IMG_VOID LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea);
+
+
+#if defined(LINUX_MEM_AREAS_DEBUG)
+IMG_VOID LinuxMemAreaRegister(LinuxMemArea *psLinuxMemArea);
+#else
+#define LinuxMemAreaRegister(X)
+#endif
+
+
+IMG_VOID *LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea);
+
+
+IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
+
+
+#define	 LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) PHYS_TO_PFN(LinuxMemAreaToCpuPAddr(psLinuxMemArea, ui32ByteOffset).uiAddr)
+
+IMG_BOOL LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea);
+
+static inline LinuxMemArea *
+LinuxMemAreaRoot(LinuxMemArea *psLinuxMemArea)
+{
+    if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        return psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
+    }
+    else
+    {
+        return psLinuxMemArea;
+    }
+}
+
+
+static inline LINUX_MEM_AREA_TYPE
+LinuxMemAreaRootType(LinuxMemArea *psLinuxMemArea)
+{
+    return LinuxMemAreaRoot(psLinuxMemArea)->eAreaType;
+}
+
+
+const IMG_CHAR *LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType);
+
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MEM_AREAS)
+const IMG_CHAR *HAPFlagsToString(IMG_UINT32 ui32Flags);
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.c
new file mode 100644
index 0000000..a273689
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.c
@@ -0,0 +1,1149 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+#include <linux/wrapper.h>
+#endif
+#include <linux/slab.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/shmparam.h>
+#include <asm/pgtable.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#include <linux/sched.h>
+#include <asm/current.h>
+#endif
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "pvrmmap.h"
+#include "mutils.h"
+#include "mmap.h"
+#include "mm.h"
+#include "pvr_debug.h"
+#include "osfunc.h"
+#include "proc.h"
+#include "mutex.h"
+#include "handle.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "bridged_support.h"
+#if defined(SUPPORT_DRI_DRM)
+#include "pvr_drm.h"
+#endif
+
+#if !defined(PVR_SECURE_HANDLES)
+#error "The mmap code requires PVR_SECURE_HANDLES"
+#endif
+
+static struct mutex g_sMMapMutex;
+
+static LinuxKMemCache *g_psMemmapCache = NULL;
+static LIST_HEAD(g_sMMapAreaList);
+static LIST_HEAD(g_sMMapOffsetStructList);
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+static IMG_UINT32 g_ui32RegisteredAreas = 0;
+static IMG_UINT32 g_ui32TotalByteSize = 0;
+#endif
+
+
+#if defined(PVR_PROC_USE_SEQ_FILE) && defined(DEBUG_LINUX_MMAP_AREAS)
+static struct proc_dir_entry *g_ProcMMap;
+#endif
+
+#define	FIRST_PHYSICAL_PFN	0
+#define	LAST_PHYSICAL_PFN	0x7fffffffUL
+#define	FIRST_SPECIAL_PFN	(LAST_PHYSICAL_PFN + 1)
+#define	LAST_SPECIAL_PFN	0xffffffffUL
+
+#define	MAX_MMAP_HANDLE		0x7fffffffUL
+
+static inline IMG_BOOL
+PFNIsPhysical(IMG_UINT32 pfn)
+{
+
+	return ((pfn >= FIRST_PHYSICAL_PFN) && (pfn <= LAST_PHYSICAL_PFN)) ? IMG_TRUE : IMG_FALSE;
+}
+
+static inline IMG_BOOL
+PFNIsSpecial(IMG_UINT32 pfn)
+{
+
+	return ((pfn >= FIRST_SPECIAL_PFN) && (pfn <= LAST_SPECIAL_PFN)) ? IMG_TRUE : IMG_FALSE;
+}
+
+static inline IMG_HANDLE
+MMapOffsetToHandle(IMG_UINT32 pfn)
+{
+	if (PFNIsPhysical(pfn))
+	{
+		PVR_ASSERT(PFNIsPhysical(pfn));
+		return IMG_NULL;
+	}
+
+	return (IMG_HANDLE)(pfn - FIRST_SPECIAL_PFN);
+}
+
+static inline IMG_UINT32
+HandleToMMapOffset(IMG_HANDLE hHandle)
+{
+	IMG_UINT32 ulHandle = (IMG_UINT32)hHandle;
+
+	if (PFNIsSpecial(ulHandle))
+	{
+		PVR_ASSERT(PFNIsSpecial(ulHandle));
+		return 0;
+	}
+
+	return ulHandle + FIRST_SPECIAL_PFN;
+}
+
+static inline IMG_BOOL
+LinuxMemAreaUsesPhysicalMap(LinuxMemArea *psLinuxMemArea)
+{
+    return LinuxMemAreaPhysIsContig(psLinuxMemArea);
+}
+
+static inline IMG_UINT32
+GetCurrentThreadID(IMG_VOID)
+{
+
+	return (IMG_UINT32)current->pid;
+}
+
+static PKV_OFFSET_STRUCT
+CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct;
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+    const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+    PVR_DPF((PVR_DBG_MESSAGE,
+             "%s(%s, psLinuxMemArea: 0x%p, ui32AllocFlags: 0x%8lx)",
+             __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags));
+#endif
+
+    PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+    PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+    psOffsetStruct = KMemCacheAllocWrapper(g_psMemmapCache, GFP_KERNEL);
+    if(psOffsetStruct == IMG_NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR,"PVRMMapRegisterArea: Couldn't alloc another mapping record from cache"));
+        return IMG_NULL;
+    }
+
+    psOffsetStruct->ui32MMapOffset = ui32Offset;
+
+    psOffsetStruct->psLinuxMemArea = psLinuxMemArea;
+
+    psOffsetStruct->ui32Mapped = 0;
+
+    psOffsetStruct->ui32RealByteSize = ui32RealByteSize;
+
+
+    psOffsetStruct->ui32TID = GetCurrentThreadID();
+
+    psOffsetStruct->ui32PID = OSGetCurrentProcessIDKM();
+
+    psOffsetStruct->bOnMMapList = IMG_FALSE;
+
+    psOffsetStruct->ui32RefCount = 0;
+
+    psOffsetStruct->ui32UserVAddr = 0;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+    psOffsetStruct->pszName = pszName;
+#endif
+
+    list_add_tail(&psOffsetStruct->sAreaItem, &psLinuxMemArea->sMMapOffsetStructList);
+
+    return psOffsetStruct;
+}
+
+
+static IMG_VOID
+DestroyOffsetStruct(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+    list_del(&psOffsetStruct->sAreaItem);
+
+    if (psOffsetStruct->bOnMMapList)
+    {
+        list_del(&psOffsetStruct->sMMapItem);
+    }
+
+    PVR_DPF((PVR_DBG_MESSAGE, "%s: Table entry: "
+             "psLinuxMemArea=0x%08lX, CpuPAddr=0x%08lX", __FUNCTION__,
+             psOffsetStruct->psLinuxMemArea,
+             LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea, 0)));
+
+    KMemCacheFreeWrapper(g_psMemmapCache, psOffsetStruct);
+}
+
+
+static inline IMG_VOID
+DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea,
+                               IMG_UINT32 *pui32RealByteSize,
+                               IMG_UINT32 *pui32ByteOffset)
+{
+    IMG_UINT32 ui32PageAlignmentOffset;
+    IMG_CPU_PHYADDR CpuPAddr;
+
+    CpuPAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0);
+    ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr);
+
+    *pui32ByteOffset = ui32PageAlignmentOffset;
+
+    *pui32RealByteSize = PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset);
+}
+
+
+PVRSRV_ERROR
+PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+				IMG_HANDLE hMHandle,
+                                IMG_UINT32 *pui32MMapOffset,
+                                IMG_UINT32 *pui32ByteOffset,
+                                IMG_UINT32 *pui32RealByteSize,
+				IMG_UINT32 *pui32UserVAddr)
+{
+    LinuxMemArea *psLinuxMemArea;
+    PKV_OFFSET_STRUCT psOffsetStruct;
+    IMG_HANDLE hOSMemHandle;
+    PVRSRV_ERROR eError;
+
+    mutex_lock(&g_sMMapMutex);
+
+    PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
+
+    eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
+    if (eError != PVRSRV_OK)
+    {
+	PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle 0x%lx failed", __FUNCTION__, hMHandle));
+
+	goto exit_unlock;
+    }
+
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+    DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+                                   pui32RealByteSize,
+                                   pui32ByteOffset);
+
+
+    list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+    {
+        if (psPerProc->ui32PID == psOffsetStruct->ui32PID)
+        {
+
+	   PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize);
+
+	   *pui32MMapOffset = psOffsetStruct->ui32MMapOffset;
+	   *pui32UserVAddr = psOffsetStruct->ui32UserVAddr;
+	   psOffsetStruct->ui32RefCount++;
+
+	   eError = PVRSRV_OK;
+	   goto exit_unlock;
+        }
+    }
+
+
+    *pui32UserVAddr = 0;
+
+    if (LinuxMemAreaUsesPhysicalMap(psLinuxMemArea))
+    {
+        *pui32MMapOffset = LinuxMemAreaToCpuPFN(psLinuxMemArea, 0);
+        PVR_ASSERT(PFNIsPhysical(*pui32MMapOffset));
+    }
+    else
+    {
+        *pui32MMapOffset = HandleToMMapOffset(hMHandle);
+        PVR_ASSERT(PFNIsSpecial(*pui32MMapOffset));
+    }
+
+    psOffsetStruct = CreateOffsetStruct(psLinuxMemArea, *pui32MMapOffset, *pui32RealByteSize);
+    if (psOffsetStruct == IMG_NULL)
+    {
+        eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+	goto exit_unlock;
+    }
+
+
+    list_add_tail(&psOffsetStruct->sMMapItem, &g_sMMapOffsetStructList);
+
+    psOffsetStruct->bOnMMapList = IMG_TRUE;
+
+    psOffsetStruct->ui32RefCount++;
+
+    eError = PVRSRV_OK;
+
+exit_unlock:
+    mutex_unlock(&g_sMMapMutex);
+
+    return eError;
+}
+
+
+PVRSRV_ERROR
+PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+				IMG_HANDLE hMHandle,
+				IMG_BOOL *pbMUnmap,
+				IMG_UINT32 *pui32RealByteSize,
+                                IMG_UINT32 *pui32UserVAddr)
+{
+    LinuxMemArea *psLinuxMemArea;
+    PKV_OFFSET_STRUCT psOffsetStruct;
+    IMG_HANDLE hOSMemHandle;
+    PVRSRV_ERROR eError;
+    IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+    mutex_lock(&g_sMMapMutex);
+
+    PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
+
+    eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
+    if (eError != PVRSRV_OK)
+    {
+	PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle 0x%lx failed", __FUNCTION__, hMHandle));
+
+	goto exit_unlock;
+    }
+
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+
+    list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+    {
+        if (psOffsetStruct->ui32PID == ui32PID)
+        {
+	    if (psOffsetStruct->ui32RefCount == 0)
+	    {
+		PVR_DPF((PVR_DBG_ERROR, "%s: Attempt to release mmap data with zero reference count for offset struct 0x%p, memory area 0x%p", __FUNCTION__, psOffsetStruct, psLinuxMemArea));
+		eError = PVRSRV_ERROR_GENERIC;
+		goto exit_unlock;
+	    }
+
+	    psOffsetStruct->ui32RefCount--;
+
+	    *pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->ui32UserVAddr != 0));
+
+	    *pui32UserVAddr = (*pbMUnmap) ? psOffsetStruct->ui32UserVAddr : 0;
+	    *pui32RealByteSize = (*pbMUnmap) ? psOffsetStruct->ui32RealByteSize : 0;
+
+	    eError = PVRSRV_OK;
+	    goto exit_unlock;
+        }
+    }
+
+
+    PVR_DPF((PVR_DBG_ERROR, "%s: Mapping data not found for handle 0x%lx (memory area 0x%p)", __FUNCTION__, hMHandle, psLinuxMemArea));
+
+    eError =  PVRSRV_ERROR_GENERIC;
+
+exit_unlock:
+    mutex_unlock(&g_sMMapMutex);
+
+    return eError;
+}
+
+static inline PKV_OFFSET_STRUCT
+FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct;
+    IMG_UINT32 ui32TID = GetCurrentThreadID();
+    IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+    list_for_each_entry(psOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
+    {
+        if (ui32Offset == psOffsetStruct->ui32MMapOffset && ui32RealByteSize == psOffsetStruct->ui32RealByteSize && psOffsetStruct->ui32PID == ui32PID)
+        {
+
+	    if (!PFNIsPhysical(ui32Offset) || psOffsetStruct->ui32TID == ui32TID)
+	    {
+	        return psOffsetStruct;
+	    }
+        }
+    }
+
+    return IMG_NULL;
+}
+
+
+static IMG_BOOL
+DoMapToUser(LinuxMemArea *psLinuxMemArea,
+            struct vm_area_struct* ps_vma,
+            IMG_UINT32 ui32ByteOffset)
+{
+    IMG_UINT32 ui32ByteSize;
+
+    if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea),
+                    ps_vma,
+                    psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset + ui32ByteOffset);
+    }
+
+
+    ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+    PVR_ASSERT(ADDR_TO_PAGE_OFFSET(ui32ByteSize) == 0);
+
+#if defined (__sparc__)
+
+#error "SPARC not supported"
+#endif
+
+    if (PFNIsPhysical(ps_vma->vm_pgoff))
+    {
+	IMG_INT result;
+
+	PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea));
+	PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) == ps_vma->vm_pgoff);
+
+
+	result = IO_REMAP_PFN_RANGE(ps_vma, ps_vma->vm_start, ps_vma->vm_pgoff, ui32ByteSize, ps_vma->vm_page_prot);
+
+        if(result == 0)
+        {
+            return IMG_TRUE;
+        }
+
+        PVR_DPF((PVR_DBG_MESSAGE, "%s: Failed to map contiguous physical address range (%d), trying non-contiguous path", __FUNCTION__, result));
+    }
+
+    {
+
+        IMG_UINT32 ulVMAPos;
+	IMG_UINT32 ui32ByteEnd = ui32ByteOffset + ui32ByteSize;
+	IMG_UINT32 ui32PA;
+
+
+	for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
+	{
+	    IMG_UINT32 pfn =  LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+
+	    if (!pfn_valid(pfn))
+	    {
+                PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x%lx", __FUNCTION__, pfn));
+                return IMG_FALSE;
+	    }
+	}
+
+
+        ulVMAPos = ps_vma->vm_start;
+	for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
+	{
+	    IMG_UINT32 pfn;
+	    struct page *psPage;
+	    IMG_INT result;
+
+	    pfn =  LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+	    PVR_ASSERT(pfn_valid(pfn));
+
+	    psPage = pfn_to_page(pfn);
+
+	    result = VM_INSERT_PAGE(ps_vma,  ulVMAPos, psPage);
+            if(result != 0)
+            {
+                PVR_DPF((PVR_DBG_ERROR,"%s: Error - VM_INSERT_PAGE failed (%d)", __FUNCTION__, result));
+                return IMG_FALSE;
+            }
+            ulVMAPos += PAGE_SIZE;
+        }
+    }
+
+    return IMG_TRUE;
+}
+
+
+static IMG_VOID
+MMapVOpenNoLock(struct vm_area_struct* ps_vma)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+    PVR_ASSERT(psOffsetStruct != IMG_NULL)
+    psOffsetStruct->ui32Mapped++;
+    PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+
+    if (psOffsetStruct->ui32Mapped > 1)
+    {
+	PVR_DPF((PVR_DBG_WARNING, "%s: Offset structure 0x%p is being shared across processes (psOffsetStruct->ui32Mapped: %lu)", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32Mapped));
+        PVR_ASSERT((ps_vma->vm_flags & VM_DONTCOPY) == 0);
+    }
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+    PVR_DPF((PVR_DBG_MESSAGE,
+             "%s: psLinuxMemArea 0x%p, KVAddress 0x%p MMapOffset %ld, ui32Mapped %d",
+             __FUNCTION__,
+             psOffsetStruct->psLinuxMemArea,
+             LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
+             psOffsetStruct->ui32MMapOffset,
+             psOffsetStruct->ui32Mapped));
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+    MOD_INC_USE_COUNT;
+#endif
+}
+
+
+static void
+MMapVOpen(struct vm_area_struct* ps_vma)
+{
+    mutex_lock(&g_sMMapMutex);
+
+    MMapVOpenNoLock(ps_vma);
+
+    mutex_unlock(&g_sMMapMutex);
+}
+
+
+static IMG_VOID
+MMapVCloseNoLock(struct vm_area_struct* ps_vma)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+    PVR_ASSERT(psOffsetStruct != IMG_NULL)
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+    PVR_DPF((PVR_DBG_MESSAGE,
+             "%s: psLinuxMemArea 0x%p, CpuVAddr 0x%p ui32MMapOffset %ld, ui32Mapped %d",
+             __FUNCTION__,
+             psOffsetStruct->psLinuxMemArea,
+             LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
+             psOffsetStruct->ui32MMapOffset,
+             psOffsetStruct->ui32Mapped));
+#endif
+
+    PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+    psOffsetStruct->ui32Mapped--;
+    if (psOffsetStruct->ui32Mapped == 0)
+    {
+	if (psOffsetStruct->ui32RefCount != 0)
+	{
+	        PVR_DPF((PVR_DBG_MESSAGE, "%s: psOffsetStruct 0x%p has non-zero reference count (ui32RefCount = %lu). User mode address of start of mapping: 0x%lx", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32RefCount, psOffsetStruct->ui32UserVAddr));
+	}
+
+	DestroyOffsetStruct(psOffsetStruct);
+    }
+
+    ps_vma->vm_private_data = NULL;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+    MOD_DEC_USE_COUNT;
+#endif
+}
+
+static void
+MMapVClose(struct vm_area_struct* ps_vma)
+{
+    mutex_lock(&g_sMMapMutex);
+
+    MMapVCloseNoLock(ps_vma);
+
+    mutex_unlock(&g_sMMapMutex);
+}
+
+
+static struct vm_operations_struct MMapIOOps =
+{
+	.open=MMapVOpen,
+	.close=MMapVClose
+};
+
+
+int
+PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
+{
+    IMG_UINT32 ui32ByteSize;
+    PKV_OFFSET_STRUCT psOffsetStruct;
+    int iRetVal = 0;
+
+    PVR_UNREFERENCED_PARAMETER(pFile);
+
+    mutex_lock(&g_sMMapMutex);
+
+    ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+
+
+    PVR_DPF((PVR_DBG_MESSAGE, "%s: Received mmap(2) request with ui32MMapOffset 0x%08lx,"
+                              " and ui32ByteSize %ld(0x%08lx)",
+            __FUNCTION__,
+            ps_vma->vm_pgoff,
+            ui32ByteSize, ui32ByteSize));
+
+    psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, ui32ByteSize);
+    if (psOffsetStruct == IMG_NULL)
+    {
+#if defined(SUPPORT_DRI_DRM)
+        mutex_unlock(&g_sMMapMutex);
+
+
+        return drm_mmap(pFile, ps_vma);
+#else
+        PVR_UNREFERENCED_PARAMETER(pFile);
+
+#if 0 /* FIXME: crash when call to print debug messages */
+        PVR_DPF((PVR_DBG_ERROR,
+             "%s: Attempted to mmap unregistered area at vm_pgoff %ld",
+             __FUNCTION__, ps_vma->vm_pgoff));
+#endif
+        iRetVal = -EINVAL;
+#endif
+        goto unlock_and_return;
+    }
+    list_del(&psOffsetStruct->sMMapItem);
+    psOffsetStruct->bOnMMapList = IMG_FALSE;
+
+
+    if (((ps_vma->vm_flags & VM_WRITE) != 0) &&
+        ((ps_vma->vm_flags & VM_SHARED) == 0))
+    {
+#if 0 /* FIXME: crash when call to print debug messages */
+        PVR_DPF((PVR_DBG_ERROR, "%s: Cannot mmap non-shareable writable areas", __FUNCTION__));
+#endif
+        iRetVal = -EINVAL;
+        goto unlock_and_return;
+    }
+
+
+#if 0 /* FIXME: crash when call to print debug messages */
+    PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped psLinuxMemArea 0x%p\n",
+         __FUNCTION__, psOffsetStruct->psLinuxMemArea));
+#endif
+    ps_vma->vm_flags |= VM_RESERVED;
+    ps_vma->vm_flags |= VM_IO;
+
+
+    ps_vma->vm_flags |= VM_DONTEXPAND;
+
+
+    ps_vma->vm_flags |= VM_DONTCOPY;
+
+    ps_vma->vm_private_data = (void *)psOffsetStruct;
+
+    switch(psOffsetStruct->psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK)
+    {
+        case PVRSRV_HAP_CACHED:
+
+            break;
+        case PVRSRV_HAP_WRITECOMBINE:
+	    ps_vma->vm_page_prot = PGPROT_WC(ps_vma->vm_page_prot);
+            break;
+        case PVRSRV_HAP_UNCACHED:
+            ps_vma->vm_page_prot = PGPROT_UC(ps_vma->vm_page_prot);
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type", __FUNCTION__));
+	    iRetVal = -EINVAL;
+	    goto unlock_and_return;
+    }
+
+
+    ps_vma->vm_ops = &MMapIOOps;
+
+    if(!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0))
+    {
+        iRetVal = -EAGAIN;
+        goto unlock_and_return;
+    }
+
+    PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0)
+
+    psOffsetStruct->ui32UserVAddr = ps_vma->vm_start;
+
+
+    MMapVOpenNoLock(ps_vma);
+
+#if 0 /* FIXME: crash when call to print debug messages */
+    PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n",
+             __FUNCTION__, ps_vma->vm_pgoff));
+#endif
+
+unlock_and_return:
+    if (iRetVal != 0 && psOffsetStruct != IMG_NULL)
+    {
+	DestroyOffsetStruct(psOffsetStruct);
+    }
+
+    mutex_unlock(&g_sMMapMutex);
+
+    return iRetVal;
+}
+
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void ProcSeqStartstopMMapRegistations(struct seq_file *sfile,IMG_BOOL start)
+{
+	if(start)
+	{
+	    mutex_lock(&g_sMMapMutex);
+	}
+	else
+	{
+	    mutex_unlock(&g_sMMapMutex);
+	}
+}
+
+
+static void* ProcSeqOff2ElementMMapRegistrations(struct seq_file *sfile, loff_t off)
+{
+    LinuxMemArea *psLinuxMemArea;
+	if(!off)
+	{
+		return PVR_PROC_SEQ_START_TOKEN;
+	}
+
+    list_for_each_entry(psLinuxMemArea, &g_sMMapAreaList, sMMapItem)
+    {
+        PKV_OFFSET_STRUCT psOffsetStruct;
+
+	 	list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+        {
+	    	off--;
+	    	if (off == 0)
+	    	{
+				PVR_ASSERT(psOffsetStruct->psLinuxMemArea == psLinuxMemArea);
+				return (void*)psOffsetStruct;
+		    }
+        }
+    }
+	return (void*)0;
+}
+
+static void* ProcSeqNextMMapRegistrations(struct seq_file *sfile,void* el,loff_t off)
+{
+	return ProcSeqOff2ElementMMapRegistrations(sfile,off);
+}
+
+
+static void ProcSeqShowMMapRegistrations(struct seq_file *sfile,void* el)
+{
+	KV_OFFSET_STRUCT *psOffsetStruct = (KV_OFFSET_STRUCT*)el;
+    LinuxMemArea *psLinuxMemArea;
+	IMG_UINT32 ui32RealByteSize;
+	IMG_UINT32 ui32ByteOffset;
+
+	if(el == PVR_PROC_SEQ_START_TOKEN)
+	{
+        seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+						  "Allocations registered for mmap: %lu\n"
+                          "In total these areas correspond to %lu bytes\n"
+                          "psLinuxMemArea "
+						  "UserVAddr "
+						  "KernelVAddr "
+						  "CpuPAddr "
+                          "MMapOffset "
+                          "ByteLength "
+                          "LinuxMemType             "
+						  "Pid   Name     Flags\n",
+#else
+                          "<mmap_header>\n"
+                          "\t<count>%lu</count>\n"
+                          "\t<bytes>%lu</bytes>\n"
+                          "</mmap_header>\n",
+#endif
+						  g_ui32RegisteredAreas,
+                          g_ui32TotalByteSize
+                          );
+		return;
+	}
+
+	psLinuxMemArea = psOffsetStruct->psLinuxMemArea;
+
+	DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+									&ui32RealByteSize,
+									&ui32ByteOffset);
+
+	seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+						"%-8p       %08lx %-8p %08lx %08lx   %-8ld   %-24s %-5lu %-8s %08lx(%s)\n",
+#else
+                        "<mmap_record>\n"
+						"\t<pointer>%-8p</pointer>\n"
+                        "\t<user_virtual>%-8lx</user_virtual>\n"
+                        "\t<kernel_virtual>%-8p</kernel_virtual>\n"
+                        "\t<cpu_physical>%08lx</cpu_physical>\n"
+                        "\t<mmap_offset>%08lx</mmap_offset>\n"
+                        "\t<bytes>%-8ld</bytes>\n"
+                        "\t<linux_mem_area_type>%-24s</linux_mem_area_type>\n"
+                        "\t<pid>%-5lu</pid>\n"
+                        "\t<name>%-8s</name>\n"
+                        "\t<flags>%08lx</flags>\n"
+                        "\t<flags_string>%s</flags_string>\n"
+                        "</mmap_record>\n",
+#endif
+                        psLinuxMemArea,
+						psOffsetStruct->ui32UserVAddr + ui32ByteOffset,
+						LinuxMemAreaToCpuVAddr(psLinuxMemArea),
+                        LinuxMemAreaToCpuPAddr(psLinuxMemArea,0).uiAddr,
+						psOffsetStruct->ui32MMapOffset,
+						psLinuxMemArea->ui32ByteSize,
+                        LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType),
+						psOffsetStruct->ui32PID,
+						psOffsetStruct->pszName,
+						psLinuxMemArea->ui32AreaFlags,
+                        HAPFlagsToString(psLinuxMemArea->ui32AreaFlags));
+}
+
+#else
+
+static off_t
+PrintMMapRegistrations(IMG_CHAR *buffer, size_t size, off_t off)
+{
+    LinuxMemArea *psLinuxMemArea;
+    off_t Ret;
+
+    mutex_lock(&g_sMMapMutex);
+
+    if(!off)
+    {
+		Ret = printAppend(buffer, size, 0,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+						  "Allocations registered for mmap: %lu\n"
+                          "In total these areas correspond to %lu bytes\n"
+                          "psLinuxMemArea "
+						  "UserVAddr "
+						  "KernelVAddr "
+						  "CpuPAddr "
+                          "MMapOffset "
+                          "ByteLength "
+                          "LinuxMemType             "
+						  "Pid   Name     Flags\n",
+#else
+                          "<mmap_header>\n"
+                          "\t<count>%lu</count>\n"
+                          "\t<bytes>%lu</bytes>\n"
+                          "</mmap_header>\n",
+#endif
+						  g_ui32RegisteredAreas,
+                          g_ui32TotalByteSize
+                          );
+
+        goto unlock_and_return;
+    }
+
+    if (size < 135)
+    {
+		Ret = 0;
+        goto unlock_and_return;
+    }
+
+    PVR_ASSERT(off != 0);
+    list_for_each_entry(psLinuxMemArea, &g_sMMapAreaList, sMMapItem)
+    {
+        PKV_OFFSET_STRUCT psOffsetStruct;
+
+	list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+        {
+	    off--;
+	    if (off == 0)
+	    {
+		IMG_UINT32 ui32RealByteSize;
+		IMG_UINT32 ui32ByteOffset;
+
+		PVR_ASSERT(psOffsetStruct->psLinuxMemArea == psLinuxMemArea);
+
+		DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+                                   &ui32RealByteSize,
+                                   &ui32ByteOffset);
+
+                Ret =  printAppend (buffer, size, 0,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+						"%-8p       %08lx %-8p %08lx %08lx   %-8ld   %-24s %-5lu %-8s %08lx(%s)\n",
+#else
+                        "<mmap_record>\n"
+						"\t<pointer>%-8p</pointer>\n"
+                        "\t<user_virtual>%-8lx</user_virtual>\n"
+                        "\t<kernel_virtual>%-8p</kernel_virtual>\n"
+                        "\t<cpu_physical>%08lx</cpu_physical>\n"
+                        "\t<mmap_offset>%08lx</mmap_offset>\n"
+                        "\t<bytes>%-8ld</bytes>\n"
+                        "\t<linux_mem_area_type>%-24s</linux_mem_area_type>\n"
+                        "\t<pid>%-5lu</pid>\n"
+                        "\t<name>%-8s</name>\n"
+                        "\t<flags>%08lx</flags>\n"
+                        "\t<flags_string>%s</flags_string>\n"
+                        "</mmap_record>\n",
+#endif
+                        psLinuxMemArea,
+			psOffsetStruct->ui32UserVAddr + ui32ByteOffset,
+						LinuxMemAreaToCpuVAddr(psLinuxMemArea),
+                        LinuxMemAreaToCpuPAddr(psLinuxMemArea,0).uiAddr,
+						psOffsetStruct->ui32MMapOffset,
+						psLinuxMemArea->ui32ByteSize,
+                        LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType),
+						psOffsetStruct->ui32PID,
+						psOffsetStruct->pszName,
+						psLinuxMemArea->ui32AreaFlags,
+                        HAPFlagsToString(psLinuxMemArea->ui32AreaFlags));
+		goto unlock_and_return;
+	    }
+        }
+    }
+    Ret = END_OF_FILE;
+
+unlock_and_return:
+    mutex_unlock(&g_sMMapMutex);
+    return Ret;
+}
+#endif
+#endif
+
+
+PVRSRV_ERROR
+PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVRSRV_ERROR eError;
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+    const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+    mutex_lock(&g_sMMapMutex);
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+    PVR_DPF((PVR_DBG_MESSAGE,
+             "%s(%s, psLinuxMemArea 0x%p, ui32AllocFlags 0x%8lx)",
+             __FUNCTION__, pszName, psLinuxMemArea,  psLinuxMemArea->ui32AreaFlags));
+#endif
+
+    PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+
+    if(psLinuxMemArea->bMMapRegistered)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "%s: psLinuxMemArea 0x%p is already registered",
+                __FUNCTION__, psLinuxMemArea));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+	goto exit_unlock;
+    }
+
+    list_add_tail(&psLinuxMemArea->sMMapItem, &g_sMMapAreaList);
+
+    psLinuxMemArea->bMMapRegistered = IMG_TRUE;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+    g_ui32RegisteredAreas++;
+
+    if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        g_ui32TotalByteSize += psLinuxMemArea->ui32ByteSize;
+    }
+#endif
+
+    eError = PVRSRV_OK;
+
+exit_unlock:
+    mutex_unlock(&g_sMMapMutex);
+
+    return eError;
+}
+
+
+PVRSRV_ERROR
+PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVRSRV_ERROR eError;
+    PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
+
+    mutex_lock(&g_sMMapMutex);
+
+    PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+    list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+    {
+	if (psOffsetStruct->ui32Mapped != 0)
+	{
+	     PVR_DPF((PVR_DBG_ERROR, "%s: psOffsetStruct 0x%p for memory area 0x0x%p is still mapped; psOffsetStruct->ui32Mapped %lu",  __FUNCTION__, psOffsetStruct, psLinuxMemArea, psOffsetStruct->ui32Mapped));
+		eError = PVRSRV_ERROR_GENERIC;
+		goto exit_unlock;
+	}
+	else
+	{
+
+	     PVR_DPF((PVR_DBG_WARNING, "%s: psOffsetStruct 0x%p was never mapped",  __FUNCTION__, psOffsetStruct));
+	}
+
+	PVR_ASSERT((psOffsetStruct->ui32Mapped == 0) && psOffsetStruct->bOnMMapList);
+
+	DestroyOffsetStruct(psOffsetStruct);
+    }
+
+    list_del(&psLinuxMemArea->sMMapItem);
+
+    psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+    g_ui32RegisteredAreas--;
+    if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        g_ui32TotalByteSize -= psLinuxMemArea->ui32ByteSize;
+    }
+#endif
+
+    eError = PVRSRV_OK;
+
+exit_unlock:
+    mutex_unlock(&g_sMMapMutex);
+    return eError;
+}
+
+
+PVRSRV_ERROR
+LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
+{
+    PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+    return PVRSRV_OK;
+}
+
+IMG_VOID
+LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
+    IMG_BOOL bWarn = IMG_FALSE;
+    IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+    PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+    mutex_lock(&g_sMMapMutex);
+
+    list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
+    {
+	if (psOffsetStruct->ui32PID == ui32PID)
+	{
+	    if (!bWarn)
+	    {
+		PVR_DPF((PVR_DBG_WARNING, "%s: process has unmapped offset structures. Removing them", __FUNCTION__));
+		bWarn = IMG_TRUE;
+	    }
+	    PVR_ASSERT(psOffsetStruct->ui32Mapped == 0);
+	    PVR_ASSERT(psOffsetStruct->bOnMMapList);
+
+	    DestroyOffsetStruct(psOffsetStruct);
+	}
+    }
+
+    mutex_unlock(&g_sMMapMutex);
+}
+
+
+PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+    PVRSRV_ERROR eError;
+
+    eError = PVRSRVSetMaxHandle(psHandleBase, MAX_MMAP_HANDLE);
+    if (eError != PVRSRV_OK)
+    {
+	PVR_DPF((PVR_DBG_ERROR,"%s: failed to set handle limit (%d)", __FUNCTION__, eError));
+	return eError;
+    }
+
+    return eError;
+}
+
+
+IMG_VOID
+PVRMMapInit(IMG_VOID)
+{
+    mutex_init(&g_sMMapMutex);
+
+    g_psMemmapCache = KMemCacheCreateWrapper("img-mmap", sizeof(KV_OFFSET_STRUCT), 0, 0);
+    if (!g_psMemmapCache)
+    {
+        PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
+	goto error;
+    }
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+#ifdef PVR_PROC_USE_SEQ_FILE
+	g_ProcMMap = CreateProcReadEntrySeq("mmap", NULL,
+						  ProcSeqNextMMapRegistrations,
+						  ProcSeqShowMMapRegistrations,
+						  ProcSeqOff2ElementMMapRegistrations,
+						  ProcSeqStartstopMMapRegistations
+						 );
+#else
+    CreateProcReadEntry("mmap", PrintMMapRegistrations);
+#endif
+#endif
+    return;
+
+error:
+    PVRMMapCleanup();
+    return;
+}
+
+
+IMG_VOID
+PVRMMapCleanup(IMG_VOID)
+{
+    PVRSRV_ERROR eError;
+
+    if (!list_empty(&g_sMMapAreaList))
+    {
+	LinuxMemArea *psLinuxMemArea, *psTmpMemArea;
+
+	PVR_DPF((PVR_DBG_ERROR, "%s: Memory areas are still registered with MMap", __FUNCTION__));
+
+	PVR_TRACE(("%s: Unregistering memory areas", __FUNCTION__));
+	list_for_each_entry_safe(psLinuxMemArea, psTmpMemArea, &g_sMMapAreaList, sMMapItem)
+	{
+		eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: PVRMMapRemoveRegisteredArea failed (%d)", __FUNCTION__, eError));
+		}
+		PVR_ASSERT(eError == PVRSRV_OK);
+
+		LinuxMemAreaDeepFree(psLinuxMemArea);
+	}
+    }
+    PVR_ASSERT(list_empty((&g_sMMapAreaList)));
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+#ifdef PVR_PROC_USE_SEQ_FILE
+    RemoveProcEntrySeq(g_ProcMMap);
+#else
+    RemoveProcEntry("mmap");
+#endif
+#endif
+
+    if(g_psMemmapCache)
+    {
+        KMemCacheDestroyWrapper(g_psMemmapCache);
+        g_psMemmapCache = NULL;
+    }
+}
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.h
new file mode 100644
index 0000000..afc7c94
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mmap.h
@@ -0,0 +1,103 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__MMAP_H__)
+#define __MMAP_H__
+
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#include "perproc.h"
+#include "mm.h"
+
+typedef struct KV_OFFSET_STRUCT_TAG
+{
+
+    IMG_UINT32			ui32Mapped;
+
+
+    IMG_UINT32                  ui32MMapOffset;
+
+    IMG_UINT32			ui32RealByteSize;
+
+
+    LinuxMemArea                *psLinuxMemArea;
+
+
+    IMG_UINT32			ui32TID;
+
+
+    IMG_UINT32			ui32PID;
+
+
+    IMG_BOOL			bOnMMapList;
+
+
+    IMG_UINT32			ui32RefCount;
+
+
+    IMG_UINT32			ui32UserVAddr;
+
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+    const IMG_CHAR		*pszName;
+#endif
+
+
+   struct list_head		sMMapItem;
+
+
+   struct list_head		sAreaItem;
+}KV_OFFSET_STRUCT, *PKV_OFFSET_STRUCT;
+
+
+
+IMG_VOID PVRMMapInit(IMG_VOID);
+
+
+IMG_VOID PVRMMapCleanup(IMG_VOID);
+
+
+PVRSRV_ERROR PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea);
+
+
+PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea);
+
+
+PVRSRV_ERROR PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+					     IMG_HANDLE hMHandle,
+                                             IMG_UINT32 *pui32MMapOffset,
+                                             IMG_UINT32 *pui32ByteOffset,
+                                             IMG_UINT32 *pui32RealByteSize,						     IMG_UINT32 *pui32UserVAddr);
+
+PVRSRV_ERROR
+PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+				IMG_HANDLE hMHandle,
+				IMG_BOOL *pbMUnmap,
+				IMG_UINT32 *pui32RealByteSize,
+                                IMG_UINT32 *pui32UserVAddr);
+
+int PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma);
+
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/module.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/module.c
new file mode 100644
index 0000000..0fd336b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/module.c
@@ -0,0 +1,756 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(SUPPORT_DRI_DRM)
+
+	#if defined(LDM_PLATFORM)
+		#define	PVR_LDM_PLATFORM_MODULE
+		#define	PVR_LDM_MODULE
+	#else
+		#if defined(LDM_PCI)
+			#define PVR_LDM_PCI_MODULE
+			#define	PVR_LDM_MODULE
+		#endif
+	#endif
+#endif
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#endif
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+#include <linux/platform_device.h>
+#endif
+
+#if defined(PVR_LDM_PCI_MODULE)
+#include <linux/pci.h>
+#endif
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+#include <asm/uaccess.h>
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "kerneldisplay.h"
+#include "kernelbuffer.h"
+#include "sysconfig.h"
+#include "sysplb.h"
+#include "systnc.h"
+#include "pvrmmap.h"
+#include "mutils.h"
+#include "mm.h"
+#include "mmap.h"
+#include "mutex.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "perproc.h"
+#include "handle.h"
+#include "pvr_bridge_km.h"
+#include "proc.h"
+#include "pvrmodule.h"
+#include "private_data.h"
+#include "lock.h"
+#include "linkage.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#include "pvr_drm.h"
+#endif
+#define DRVNAME		"pvrsrvkm"
+#define DEVNAME		"pvrsrvkm"
+
+#if defined(SUPPORT_DRI_DRM)
+#define PRIVATE_DATA(pFile) ((pFile)->driver_priv)
+#else
+#define PRIVATE_DATA(pFile) ((pFile)->private_data)
+#endif
+
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+#ifdef DEBUG
+static IMG_INT debug = DBGPRIV_WARNING;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+#include <linux/moduleparam.h>
+module_param(debug, int, 0);
+#else
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Sets the level of debug output (default=0x4)");
+#endif
+#endif
+
+
+extern IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable);
+extern IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable);
+
+EXPORT_SYMBOL(PVRGetDisplayClassJTable);
+EXPORT_SYMBOL(PVRGetBufferClassJTable);
+
+
+#if defined(PVR_LDM_MODULE)
+static struct class *psPvrClass;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+static IMG_INT AssignedMajorNumber;
+
+static IMG_INT PVRSRVOpen(struct inode* pInode, struct file* pFile);
+static IMG_INT PVRSRVRelease(struct inode* pInode, struct file* pFile);
+
+static struct file_operations pvrsrv_fops = {
+	.owner=THIS_MODULE,
+	.unlocked_ioctl=PVRSRV_BridgeDispatchKM,
+	.open=PVRSRVOpen,
+	.release=PVRSRVRelease,
+	.mmap=PVRMMap,
+};
+#endif
+
+struct mutex gPVRSRVLock;
+
+IMG_UINT32 gui32ReleasePID;
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+static IMG_UINT32 gPVRPowerLevel;
+#endif
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+#define	LDM_DEV	struct platform_device
+#define	LDM_DRV	struct platform_driver
+#endif
+
+#if defined(PVR_LDM_PCI_MODULE)
+#define	LDM_DEV	struct pci_dev
+#define	LDM_DRV	struct pci_driver
+#endif
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+static IMG_INT PVRSRVDriverRemove(LDM_DEV *device);
+static IMG_INT PVRSRVDriverProbe(LDM_DEV *device);
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static IMG_VOID PVRSRVDriverRemove(LDM_DEV *device);
+static IMG_INT PVRSRVDriverProbe(LDM_DEV *device, const struct pci_device_id *id);
+#endif
+static IMG_INT PVRSRVDriverSuspend(LDM_DEV *device, pm_message_t state);
+static IMG_VOID PVRSRVDriverShutdown(LDM_DEV *device);
+static IMG_INT PVRSRVDriverResume(LDM_DEV *device);
+
+#if defined(PVR_LDM_PCI_MODULE)
+/* all supported platform ids */
+struct pci_device_id powervr_id_table[] __devinitdata = {
+	{ PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID_PLB) },
+	{ PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID_TNC) },
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, powervr_id_table);
+#endif
+
+static LDM_DRV powervr_driver = {
+#if defined(PVR_LDM_PLATFORM_MODULE)
+	.driver = {
+		.name		= DRVNAME,
+	},
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+	.name		= DRVNAME,
+	.id_table = powervr_id_table,
+#endif
+	.probe		= PVRSRVDriverProbe,
+#if defined(PVR_LDM_PLATFORM_MODULE)
+	.remove		= PVRSRVDriverRemove,
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+	.remove		= __devexit_p(PVRSRVDriverRemove),
+#endif
+	.suspend	= PVRSRVDriverSuspend,
+	.resume		= PVRSRVDriverResume,
+	.shutdown	= PVRSRVDriverShutdown,
+};
+
+LDM_DEV *gpsPVRLDMDev;
+
+#if defined(MODULE) && defined(PVR_LDM_PLATFORM_MODULE)
+
+static IMG_VOID PVRSRVDeviceRelease(struct device *pDevice)
+{
+	PVR_UNREFERENCED_PARAMETER(pDevice);
+}
+
+static struct platform_device powervr_device = {
+	.name			= DEVNAME,
+	.id				= -1,
+	.dev 			= {
+		.release	= PVRSRVDeviceRelease
+	}
+};
+
+#endif
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+static IMG_INT PVRSRVDriverProbe(LDM_DEV *pDevice)
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static IMG_INT __devinit PVRSRVDriverProbe(LDM_DEV *pDevice, const struct pci_device_id *id)
+#endif
+{
+	SYS_DATA *psSysData;
+
+	PVR_TRACE(("PVRSRVDriverProbe(pDevice=%p)", pDevice));
+
+#if 0
+
+	if (PerDeviceSysInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
+	{
+		return -EINVAL;
+	}
+#endif
+
+	if (SysAcquireData(&psSysData) != PVRSRV_OK)
+	{
+		gpsPVRLDMDev = pDevice;
+
+		if (SysInitialise() != PVRSRV_OK)
+		{
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+static IMG_INT PVRSRVDriverRemove(LDM_DEV *pDevice)
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static IMG_VOID __devexit PVRSRVDriverRemove(LDM_DEV *pDevice)
+#endif
+{
+	SYS_DATA *psSysData;
+
+	PVR_TRACE(("PVRSRVDriverRemove(pDevice=%p)", pDevice));
+
+	if (SysAcquireData(&psSysData) == PVRSRV_OK)
+	{
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+		if (gPVRPowerLevel != 0)
+		{
+			if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
+			{
+				gPVRPowerLevel = 0;
+			}
+		}
+#endif
+		SysDeinitialise(psSysData);
+
+		gpsPVRLDMDev = IMG_NULL;
+	}
+
+#if 0
+	if (PerDeviceSysDeInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
+	{
+		return -EINVAL;
+	}
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+	return 0;
+#endif
+#if defined (PVR_LDM_PCI_MODULE)
+	return;
+#endif
+}
+
+
+static IMG_VOID PVRSRVDriverShutdown(LDM_DEV *pDevice)
+{
+	PVR_TRACE(("PVRSRVDriverShutdown(pDevice=%p)", pDevice));
+
+	(IMG_VOID) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3);
+}
+
+#endif
+
+
+#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state)
+#else
+static IMG_INT PVRSRVDriverSuspend(LDM_DEV *pDevice, pm_message_t state)
+#endif
+{
+#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
+	PVR_TRACE(( "PVRSRVDriverSuspend(pDevice=%p)", pDevice));
+
+	if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+	{
+		return -EINVAL;
+	}
+#endif
+	return 0;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRSRVDriverResume(struct drm_device *pDevice)
+#else
+static IMG_INT PVRSRVDriverResume(LDM_DEV *pDevice)
+#endif
+{
+#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
+	PVR_TRACE(("PVRSRVDriverResume(pDevice=%p)", pDevice));
+
+	if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
+	{
+		return -EINVAL;
+	}
+#endif
+	return 0;
+}
+#endif
+
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM)
+IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
+{
+	IMG_CHAR data_buffer[2];
+	IMG_UINT32 PVRPowerLevel;
+
+	if (count != sizeof(data_buffer))
+	{
+		return -EINVAL;
+	}
+	else
+	{
+		if (copy_from_user(data_buffer, buffer, count))
+			return -EINVAL;
+		if (data_buffer[count - 1] != '\n')
+			return -EINVAL;
+		PVRPowerLevel = data_buffer[0] - '0';
+		if (PVRPowerLevel != gPVRPowerLevel)
+		{
+			if (PVRPowerLevel != 0)
+			{
+				if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+				{
+					return -EINVAL;
+				}
+			}
+			else
+			{
+				if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
+				{
+					return -EINVAL;
+				}
+			}
+
+			gPVRPowerLevel = PVRPowerLevel;
+		}
+	}
+	return (count);
+}
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el)
+{
+	seq_printf(sfile, "%lu\n", gPVRPowerLevel);
+}
+
+#else
+IMG_INT PVRProcGetPowerLevel(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+	if (off == 0) {
+		*start = (IMG_CHAR *)1;
+		return printAppend(page, count, 0, "%lu\n", gPVRPowerLevel);
+	}
+	*eof = 1;
+	return 0;
+}
+#endif
+
+#endif
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRSRVOpen(struct drm_device unref__ *dev, struct drm_file *pFile)
+#else
+static IMG_INT PVRSRVOpen(struct inode unref__ * pInode, struct file *pFile)
+#endif
+{
+	PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+	IMG_HANDLE hBlockAlloc;
+	IMG_INT iRet = -ENOMEM;
+	PVRSRV_ERROR eError;
+	IMG_UINT32 ui32PID;
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+	PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+#endif
+
+#if defined(SUPPORT_DRI_DRM)
+	PVR_UNREFERENCED_PARAMETER(dev);
+#else
+	PVR_UNREFERENCED_PARAMETER(pInode);
+#endif
+
+	mutex_lock(&gPVRSRVLock);
+
+	ui32PID = OSGetCurrentProcessIDKM();
+
+	if (PVRSRVProcessConnect(ui32PID) != PVRSRV_OK)
+		goto err_unlock;
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+	psEnvPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+	if (psEnvPerProc == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: No per-process private data", __FUNCTION__));
+		goto err_unlock;
+	}
+#endif
+
+	eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+						sizeof(PVRSRV_FILE_PRIVATE_DATA),
+						(IMG_PVOID *)&psPrivateData,
+						&hBlockAlloc,
+						"File Private Data");
+
+	if(eError != PVRSRV_OK)
+		goto err_unlock;
+
+#if defined(PVR_SECURE_FD_EXPORT)
+	psPrivateData->hKernelMemInfo = NULL;
+#endif
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+	psPrivateData->psDRMFile = pFile;
+
+	list_add_tail(&psPrivateData->sDRMAuthListItem, &psEnvPerProc->sDRMAuthListHead);
+#endif
+	psPrivateData->ui32OpenPID = ui32PID;
+	psPrivateData->hBlockAlloc = hBlockAlloc;
+	PRIVATE_DATA(pFile) = psPrivateData;
+	iRet = 0;
+err_unlock:
+	mutex_unlock(&gPVRSRVLock);
+	return iRet;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRSRVRelease(struct drm_device unref__ *dev, struct drm_file *pFile)
+#else
+static IMG_INT PVRSRVRelease(struct inode unref__ * pInode, struct file *pFile)
+#endif
+{
+	PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+
+#if defined(SUPPORT_DRI_DRM)
+	PVR_UNREFERENCED_PARAMETER(dev);
+#else
+	PVR_UNREFERENCED_PARAMETER(pInode);
+#endif
+
+	mutex_lock(&gPVRSRVLock);
+
+	psPrivateData = PRIVATE_DATA(pFile);
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+	list_del(&psPrivateData->sDRMAuthListItem);
+#endif
+
+
+	gui32ReleasePID = psPrivateData->ui32OpenPID;
+	PVRSRVProcessDisconnect(psPrivateData->ui32OpenPID);
+	gui32ReleasePID = 0;
+
+	OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+			  sizeof(PVRSRV_FILE_PRIVATE_DATA),
+			  psPrivateData, psPrivateData->hBlockAlloc);
+
+	PRIVATE_DATA(pFile) = NULL;
+
+	mutex_unlock(&gPVRSRVLock);
+	return 0;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRCore_Init(IMG_VOID)
+#else
+static IMG_INT __init PVRCore_Init(IMG_VOID)
+#endif
+{
+	IMG_INT error;
+#if !defined(PVR_LDM_MODULE)
+	PVRSRV_ERROR eError;
+#else
+	struct device *psDev;
+#endif
+
+	PVRDPFInit();
+	PVR_TRACE(("PVRCore_Init"));
+
+	mutex_init(&gPVRSRVLock);
+
+#ifdef DEBUG
+	PVRDebugSetLevel(debug);
+#endif
+
+	if (CreateProcEntries ())
+	{
+		error = -ENOMEM;
+		return error;
+	}
+
+	if (PVROSFuncInit() != PVRSRV_OK)
+	{
+		error = -ENOMEM;
+		goto init_failed;
+	}
+
+	PVRLinuxMUtilsInit();
+
+	if(LinuxMMInit() != PVRSRV_OK)
+	{
+		error = -ENOMEM;
+		goto init_failed;
+	}
+
+	LinuxBridgeInit();
+
+	PVRMMapInit();
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+	if ((error = platform_driver_register(&powervr_driver)) != 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform driver (%d)", error));
+
+		goto init_failed;
+	}
+
+#if defined(MODULE)
+	if ((error = platform_device_register(&powervr_device)) != 0)
+	{
+		platform_driver_unregister(&powervr_driver);
+
+		PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform device (%d)", error));
+
+		goto init_failed;
+	}
+#endif
+#endif
+
+#if defined(PVR_LDM_PCI_MODULE)
+	if ((error = pci_register_driver(&powervr_driver)) != 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register PCI driver (%d)", error));
+
+		goto init_failed;
+	}
+#endif
+
+#else
+
+	if ((eError = SysInitialise()) != PVRSRV_OK)
+	{
+		error = -ENODEV;
+#if defined(TCF_REV) && (TCF_REV == 110)
+		if(eError == PVRSRV_ERROR_NOT_SUPPORTED)
+		{
+			printk("\nAtlas wrapper (FPGA image) version mismatch");
+			error = -ENODEV;
+		}
+#endif
+		goto init_failed;
+	}
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+	AssignedMajorNumber = register_chrdev(0, DEVNAME, &pvrsrv_fops);
+
+	if (AssignedMajorNumber <= 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to get major number"));
+
+		error = -EBUSY;
+		goto sys_deinit;
+	}
+
+	PVR_TRACE(("PVRCore_Init: major device %d", AssignedMajorNumber));
+#endif
+
+#if defined(PVR_LDM_MODULE)
+
+	psPvrClass = class_create(THIS_MODULE, "pvr");
+
+	if (IS_ERR(psPvrClass))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create class (%ld)", PTR_ERR(psPvrClass)));
+		error = -EBUSY;
+		goto unregister_device;
+	}
+
+	psDev = device_create(psPvrClass, NULL, MKDEV(AssignedMajorNumber, 0),
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
+				  NULL,
+#endif
+				  DEVNAME);
+	if (IS_ERR(psDev))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create device (%ld)", PTR_ERR(psDev)));
+		error = -EBUSY;
+		goto destroy_class;
+	}
+#endif
+
+	return 0;
+
+#if defined(PVR_LDM_MODULE)
+destroy_class:
+	class_destroy(psPvrClass);
+unregister_device:
+	unregister_chrdev((IMG_UINT)AssignedMajorNumber, DRVNAME);
+#endif
+#if !defined(SUPPORT_DRI_DRM)
+sys_deinit:
+#endif
+#if defined(PVR_LDM_MODULE)
+#if defined(PVR_LDM_PCI_MODULE)
+	pci_unregister_driver(&powervr_driver);
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+#if defined (MODULE)
+	platform_device_unregister(&powervr_device);
+#endif
+	platform_driver_unregister(&powervr_driver);
+#endif
+
+#else
+
+	{
+		SYS_DATA *psSysData;
+
+		SysAcquireData(&psSysData);
+		if (psSysData != IMG_NULL)
+		{
+			SysDeinitialise(psSysData);
+		}
+	}
+#endif
+init_failed:
+	PVRMMapCleanup();
+	LinuxMMCleanup();
+	LinuxBridgeDeInit();
+	PVROSFuncDeInit();
+	RemoveProcEntries();
+
+	return error;
+
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_VOID PVRCore_Cleanup(IMG_VOID)
+#else
+static IMG_VOID __exit PVRCore_Cleanup(IMG_VOID)
+#endif
+{
+	SYS_DATA *psSysData;
+
+	PVR_TRACE(("PVRCore_Cleanup"));
+
+	SysAcquireData(&psSysData);
+
+#if defined(PVR_LDM_MODULE)
+	device_destroy(psPvrClass, MKDEV(AssignedMajorNumber, 0));
+	class_destroy(psPvrClass);
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+	if (
+#endif
+		unregister_chrdev((IMG_UINT)AssignedMajorNumber, DRVNAME)
+#if !(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+								;
+#else
+								)
+	{
+		PVR_DPF((PVR_DBG_ERROR," can't unregister device major %d", AssignedMajorNumber));
+	}
+#endif
+#endif
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PCI_MODULE)
+	pci_unregister_driver(&powervr_driver);
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+#if defined (MODULE)
+	platform_device_unregister(&powervr_device);
+#endif
+	platform_driver_unregister(&powervr_driver);
+#endif
+
+#else
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+	if (gPVRPowerLevel != 0)
+	{
+		if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
+		{
+			gPVRPowerLevel = 0;
+		}
+	}
+#endif
+
+	SysDeinitialise(psSysData);
+#endif
+
+	PVRMMapCleanup();
+
+	LinuxMMCleanup();
+
+	LinuxBridgeDeInit();
+
+	PVROSFuncDeInit();
+
+	RemoveProcEntries();
+
+	PVR_TRACE(("PVRCore_Cleanup: unloading"));
+}
+
+#if !defined(SUPPORT_DRI_DRM)
+module_init(PVRCore_Init);
+module_exit(PVRCore_Cleanup);
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutex.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutex.c
new file mode 100644
index 0000000..652955a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutex.c
@@ -0,0 +1,28 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+/*
+ * PVR's mutex wrapping code has been removed and we're just calling
+ * mutex_lock, mutex_unlock, etc. directly now.  Most of the wrappers
+ * here were unused, and the couple that were used simply confused
+ * the compiler about potential recursive locking.
+ */
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutex.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutex.h
new file mode 100644
index 0000000..894c1c9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutex.h
@@ -0,0 +1,37 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __INCLUDED_LINUX_MUTEX_H_
+#define __INCLUDED_LINUX_MUTEX_H_
+
+#include <linux/version.h>
+
+#include <linux/mutex.h>
+
+/*
+ * PVR's mutex wrapping code has been removed and we're just calling
+ * mutex_lock, mutex_unlock, etc. directly now.  Most of the wrappers
+ * here were unused, and the couple that were used simply confused
+ * the compiler about potential recursive locking.
+ */
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutils.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutils.c
new file mode 100644
index 0000000..ce010bf
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutils.c
@@ -0,0 +1,126 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <linux/version.h>
+
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include "img_defs.h"
+#include "pvr_debug.h"
+#include "mutils.h"
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+#define	PAT_LINUX_X86_WC	1
+
+#define	PAT_X86_ENTRY_BITS	8
+
+#define	PAT_X86_BIT_PWT		1U
+#define	PAT_X86_BIT_PCD		2U
+#define	PAT_X86_BIT_PAT		4U
+#define	PAT_X86_BIT_MASK	(PAT_X86_BIT_PAT | PAT_X86_BIT_PCD | PAT_X86_BIT_PWT)
+
+static IMG_BOOL g_write_combining_available = IMG_FALSE;
+
+#define	PROT_TO_PAT_INDEX(v, B) ((v & _PAGE_ ## B) ? PAT_X86_BIT_ ## B : 0)
+
+static inline IMG_UINT
+pvr_pat_index(pgprotval_t prot_val)
+{
+	IMG_UINT ret = 0;
+	pgprotval_t val = prot_val & _PAGE_CACHE_MASK;
+
+	ret |= PROT_TO_PAT_INDEX(val, PAT);
+	ret |= PROT_TO_PAT_INDEX(val, PCD);
+	ret |= PROT_TO_PAT_INDEX(val, PWT);
+
+	return ret;
+}
+
+static inline IMG_UINT
+pvr_pat_entry(u64 pat, IMG_UINT index)
+{
+	return (IMG_UINT)(pat >> (index * PAT_X86_ENTRY_BITS)) & PAT_X86_BIT_MASK;
+}
+
+static IMG_VOID
+PVRLinuxX86PATProbe(IMG_VOID)
+{
+
+	if (cpu_has_pat)
+	{
+		u64 pat;
+		IMG_UINT pat_index;
+		IMG_UINT pat_entry;
+
+		PVR_TRACE(("%s: PAT available", __FUNCTION__));
+
+		rdmsrl(MSR_IA32_CR_PAT, pat);
+		PVR_TRACE(("%s: Top 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat >> 32)));
+		PVR_TRACE(("%s: Bottom 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat)));
+
+		pat_index = pvr_pat_index(_PAGE_CACHE_WC);
+		PVR_TRACE(("%s: PAT index for write combining: %u", __FUNCTION__, pat_index));
+
+		pat_entry = pvr_pat_entry(pat, pat_index);
+		PVR_TRACE(("%s: PAT entry for write combining: 0x%.2x (should be 0x%.2x)", __FUNCTION__, pat_entry, PAT_LINUX_X86_WC));
+
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+		g_write_combining_available = (IMG_BOOL)(pat_entry == PAT_LINUX_X86_WC);
+#endif
+	}
+#if defined(DEBUG)
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+	if (g_write_combining_available)
+	{
+		PVR_TRACE(("%s: Write combining available via PAT", __FUNCTION__));
+	}
+	else
+	{
+		PVR_TRACE(("%s: Write combining not available", __FUNCTION__));
+	}
+#else
+	PVR_TRACE(("%s: Write combining disabled in driver build", __FUNCTION__));
+#endif
+#endif
+}
+
+pgprot_t
+pvr_pgprot_writecombine(pgprot_t prot)
+{
+
+
+    return (g_write_combining_available) ?
+		__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_MASK) | _PAGE_CACHE_WC) : pgprot_noncached(prot);
+}
+#endif
+
+IMG_VOID
+PVRLinuxMUtilsInit(IMG_VOID)
+{
+#if defined(SUPPORT_LINUX_X86_PAT)
+	PVRLinuxX86PATProbe();
+#endif
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutils.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutils.h
new file mode 100644
index 0000000..625041b
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/mutils.h
@@ -0,0 +1,93 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __IMG_LINUX_MUTILS_H__
+#define __IMG_LINUX_MUTILS_H__
+
+#include <linux/version.h>
+
+#if !(defined(__i386__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)))
+#if defined(SUPPORT_LINUX_X86_PAT)
+#undef SUPPORT_LINUX_X86_PAT
+#endif
+#endif
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+	pgprot_t pvr_pgprot_writecombine(pgprot_t prot);
+	#define	PGPROT_WC(pv)	pvr_pgprot_writecombine(pv)
+#else
+	#if defined(__arm__) || defined(__sh__)
+		#define	PGPROT_WC(pv)	pgprot_writecombine(pv)
+	#else
+		#if defined(__i386__)
+			#define	PGPROT_WC(pv)	pgprot_noncached(pv)
+		#else
+			#define PGPROT_WC(pv)	pgprot_noncached(pv)
+			#error  Unsupported architecture!
+		#endif
+	#endif
+#endif
+
+#define	PGPROT_UC(pv)	pgprot_noncached(pv)
+
+#if defined(__i386__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+	#define	IOREMAP(pa, bytes)	ioremap_cache(pa, bytes)
+#else
+	#if defined(__arm__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+		#define	IOREMAP(pa, bytes)	ioremap_cached(pa, bytes)
+	#else
+		#define IOREMAP(pa, bytes)	ioremap(pa, bytes)
+	#endif
+#endif
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+	#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+		#define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+	#else
+		#define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes)
+	#endif
+#else
+	#if defined(__arm__)
+		#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
+			#define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+		#else
+			#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+				#define	IOREMAP_WC(pa, bytes)	ioremap_nocache(pa, bytes)
+			#else
+				#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17))
+					#define	IOREMAP_WC(pa, bytes)	__ioremap(pa, bytes, L_PTE_BUFFERABLE)
+				#else
+					#define IOREMAP_WC(pa, bytes)	__ioremap(pa, bytes, , L_PTE_BUFFERABLE, 1)
+				#endif
+			#endif
+		#endif
+	#else
+		#define IOREMAP_WC(pa, bytes)	ioremap_nocache(pa, bytes)
+	#endif
+#endif
+
+#define	IOREMAP_UC(pa, bytes)	ioremap_nocache(pa, bytes)
+
+IMG_VOID PVRLinuxMUtilsInit(IMG_VOID);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/osfunc.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/osfunc.c
new file mode 100644
index 0000000..60b8a69
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/osfunc.c
@@ -0,0 +1,2529 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION 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(2,6,22))
+#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/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/osperproc.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/osperproc.c
new file mode 100644
index 0000000..6126ffd
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/osperproc.c
@@ -0,0 +1,109 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "osperproc.h"
+
+#include "env_perproc.h"
+#include "proc.h"
+
+extern IMG_UINT32 gui32ReleasePID;
+
+PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
+{
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hBlockAlloc;
+	PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+	eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
+				phOsPrivateData,
+				&hBlockAlloc,
+				"Environment per Process Data");
+
+	if (eError != PVRSRV_OK)
+	{
+		*phOsPrivateData = IMG_NULL;
+
+		PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed (%d)", __FUNCTION__, eError));
+		return eError;
+	}
+
+	psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)*phOsPrivateData;
+	OSMemSet(psEnvPerProc, 0, sizeof(*psEnvPerProc));
+
+	psEnvPerProc->hBlockAlloc = hBlockAlloc;
+
+
+	LinuxMMapPerProcessConnect(psEnvPerProc);
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+
+	INIT_LIST_HEAD(&psEnvPerProc->sDRMAuthListHead);
+#endif
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+	if (hOsPrivateData == IMG_NULL)
+	{
+		return PVRSRV_OK;
+	}
+
+	psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)hOsPrivateData;
+
+
+	LinuxMMapPerProcessDisconnect(psEnvPerProc);
+
+
+	RemovePerProcessProcDir(psEnvPerProc);
+
+	eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
+				hOsPrivateData,
+				psEnvPerProc->hBlockAlloc);
+
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: OSFreeMem failed (%d)", __FUNCTION__, eError));
+	}
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+	return LinuxMMapPerProcessHandleOptions(psHandleBase);
+}
+
+IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID)
+{
+	if(!gui32ReleasePID)
+		return NULL;
+	return PVRSRVPerProcessPrivateData(gui32ReleasePID);
+}
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pdump.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pdump.c
new file mode 100644
index 0000000..70a8892
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pdump.c
@@ -0,0 +1,658 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if defined (SUPPORT_SGX)
+#if defined (PDUMP)
+
+#include <asm/atomic.h>
+#include <stdarg.h>
+#include "sgxdefs.h"
+#include "services_headers.h"
+
+#include "pvrversion.h"
+#include "pvr_debug.h"
+
+#include "dbgdrvif.h"
+#include "sgxmmu.h"
+#include "mm.h"
+#include "pdump_km.h"
+
+#include <linux/tty.h>
+
+static IMG_BOOL PDumpWriteString2		(IMG_CHAR * pszString, IMG_UINT32 ui32Flags);
+static IMG_BOOL PDumpWriteILock			(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags);
+static IMG_VOID DbgSetFrame				(PDBG_STREAM psStream, IMG_UINT32 ui32Frame);
+static IMG_UINT32 DbgGetFrame			(PDBG_STREAM psStream);
+static IMG_VOID DbgSetMarker			(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+static IMG_UINT32 DbgWrite				(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags);
+
+#define PDUMP_DATAMASTER_PIXEL		(1)
+#define PDUMP_DATAMASTER_EDM		(3)
+
+#define MIN(a,b)       (a > b ? b : a)
+
+#define MAX_FILE_SIZE	0x40000000
+
+static atomic_t gsPDumpSuspended = ATOMIC_INIT(0);
+
+static PDBGKM_SERVICE_TABLE gpfnDbgDrv = IMG_NULL;
+
+
+
+IMG_CHAR *pszStreamName[PDUMP_NUM_STREAMS] = {	"ParamStream2",
+												"ScriptStream2",
+												"DriverInfoStream"};
+typedef struct PDBG_PDUMP_STATE_TAG
+{
+	PDBG_STREAM psStream[PDUMP_NUM_STREAMS];
+	IMG_UINT32 ui32ParamFileNum;
+
+	IMG_CHAR *pszMsg;
+	IMG_CHAR *pszScript;
+	IMG_CHAR *pszFile;
+
+} PDBG_PDUMP_STATE;
+
+static PDBG_PDUMP_STATE gsDBGPdumpState = {{IMG_NULL}, 0, IMG_NULL, IMG_NULL, IMG_NULL};
+
+#define SZ_MSG_SIZE_MAX			PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_SCRIPT_SIZE_MAX		PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_FILENAME_SIZE_MAX	PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+
+
+
+
+IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table);
+
+static inline IMG_BOOL PDumpSuspended(IMG_VOID)
+{
+	return atomic_read(&gsPDumpSuspended) != 0;
+}
+
+PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript,
+									IMG_UINT32 *pui32MaxLen)
+{
+	*phScript = (IMG_HANDLE)gsDBGPdumpState.pszScript;
+	*pui32MaxLen = SZ_SCRIPT_SIZE_MAX;
+	if ((!*phScript) || PDumpSuspended())
+	{
+		return PVRSRV_ERROR_GENERIC;
+	}
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSGetMessageString(IMG_HANDLE *phMsg,
+									 IMG_UINT32 *pui32MaxLen)
+{
+	*phMsg = (IMG_HANDLE)gsDBGPdumpState.pszMsg;
+	*pui32MaxLen = SZ_MSG_SIZE_MAX;
+	if ((!*phMsg) || PDumpSuspended())
+	{
+		return PVRSRV_ERROR_GENERIC;
+	}
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile,
+									 IMG_UINT32 *pui32MaxLen)
+{
+	*ppszFile = gsDBGPdumpState.pszFile;
+	*pui32MaxLen = SZ_FILENAME_SIZE_MAX;
+	if ((!*ppszFile) || PDumpSuspended())
+	{
+		return PVRSRV_ERROR_GENERIC;
+	}
+	return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags)
+{
+	return PDumpWriteString2(hScript, ui32Flags);
+}
+
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...)
+{
+	IMG_CHAR* pszBuf = hBuf;
+	IMG_UINT32 n;
+	va_list	vaArgs;
+
+	va_start(vaArgs, pszFormat);
+
+	n = vsnprintf(pszBuf, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+	va_end(vaArgs);
+
+	if (n>=ui32ScriptSizeMax || n==-1)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+		return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+	}
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs)
+{
+	IMG_UINT32 n;
+
+	n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+	if (n>=ui32ScriptSizeMax || n==-1)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+		return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+	}
+
+	return PVRSRV_OK;
+}
+
+IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...)
+{
+
+}
+
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...)
+{
+	IMG_UINT32 n;
+	va_list	vaArgs;
+
+	va_start(vaArgs, pszFormat);
+
+	n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+	va_end(vaArgs);
+
+	if (n>=ui32ScriptSizeMax || n==-1)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+		return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+	}
+
+	return PVRSRV_OK;
+}
+
+IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+	IMG_CHAR* pszBuf = hBuffer;
+	IMG_UINT32 ui32Count = 0;
+
+	while ((pszBuf[ui32Count]!=0) && (ui32Count<ui32BufferSizeMax) )
+	{
+		ui32Count++;
+	}
+	return(ui32Count);
+}
+
+IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+	IMG_UINT32 ui32Count = 0;
+	IMG_CHAR* pszBuf = hBuffer;
+
+
+	ui32Count = PDumpOSBuflen(hBuffer, ui32BufferSizeMax);
+
+
+	if ((ui32Count >= 1) && (pszBuf[ui32Count-1] != '\n') && (ui32Count<ui32BufferSizeMax))
+	{
+		pszBuf[ui32Count] = '\n';
+		ui32Count++;
+		pszBuf[ui32Count] = '\0';
+	}
+	if ((ui32Count >= 2) && (pszBuf[ui32Count-2] != '\r') && (ui32Count<ui32BufferSizeMax))
+	{
+		pszBuf[ui32Count-1] = '\r';
+		pszBuf[ui32Count] = '\n';
+		ui32Count++;
+		pszBuf[ui32Count] = '\0';
+	}
+}
+
+IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream)
+{
+	return (IMG_HANDLE)gsDBGPdumpState.psStream[ePDumpStream];
+}
+
+IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream)
+{
+	PDBG_STREAM psStream = gsDBGPdumpState.psStream[ePDumpStream];
+	return gpfnDbgDrv->pfnGetStreamOffset(psStream);
+}
+
+IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID)
+{
+	return gsDBGPdumpState.ui32ParamFileNum;
+}
+
+IMG_BOOL PDumpOSWriteString(IMG_HANDLE hStream,
+		IMG_UINT8 *psui8Data,
+		IMG_UINT32 ui32Size,
+		IMG_UINT32 ui32Flags)
+{
+	PDBG_STREAM psStream = (PDBG_STREAM)hStream;
+	return PDumpWriteILock(psStream,
+					psui8Data,
+					ui32Size,
+					ui32Flags);
+}
+
+IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags)
+{
+
+	PVR_UNREFERENCED_PARAMETER(hStream);
+	PVR_UNREFERENCED_PARAMETER(ui32Size);
+	PVR_UNREFERENCED_PARAMETER(ui32Size);
+}
+
+IMG_BOOL PDumpOSJTInitialised(IMG_VOID)
+{
+	if(gpfnDbgDrv)
+	{
+		return IMG_TRUE;
+	}
+	return IMG_FALSE;
+}
+
+inline IMG_BOOL PDumpOSIsSuspended(IMG_VOID)
+{
+	return atomic_read(&gsPDumpSuspended) != 0;
+}
+
+IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
+        IMG_HANDLE hOSMemHandle,
+		IMG_UINT32 ui32Offset,
+		IMG_UINT8 *pui8LinAddr,
+		IMG_UINT32 ui32PageSize,
+		IMG_DEV_PHYADDR *psDevPAddr)
+{
+	if(hOSMemHandle)
+	{
+
+		IMG_CPU_PHYADDR	sCpuPAddr;
+
+		PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
+
+		sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+		PVR_ASSERT((sCpuPAddr.uiAddr & (ui32PageSize - 1)) == 0);
+
+
+		*psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+	}
+	else
+	{
+		IMG_CPU_PHYADDR	sCpuPAddr;
+
+		PVR_UNREFERENCED_PARAMETER(ui32Offset);
+
+		sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
+		*psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+	}
+}
+
+IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
+		IMG_UINT32 ui32Offset,
+		IMG_PUINT8 pui8LinAddr,
+		IMG_UINT32 *pui32PageOffset)
+{
+	if(hOSMemHandle)
+	{
+
+		IMG_CPU_PHYADDR     sCpuPAddr;
+
+		PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
+
+		sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+	    *pui32PageOffset = sCpuPAddr.uiAddr & (HOST_PAGESIZE() -1);
+	}
+	else
+	{
+		PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+		PVR_UNREFERENCED_PARAMETER(ui32Offset);
+
+		*pui32PageOffset = (IMG_UINT32)pui8LinAddr & (HOST_PAGESIZE() - 1);
+	}
+}
+
+
+
+IMG_VOID PDumpInit(IMG_VOID)
+{
+	IMG_UINT32 i;
+
+
+	if (!gpfnDbgDrv)
+	{
+		DBGDrvGetServiceTable((IMG_VOID **)&gpfnDbgDrv);
+
+
+
+
+		if (gpfnDbgDrv == IMG_NULL)
+		{
+			return;
+		}
+
+		if(!gsDBGPdumpState.pszFile)
+		{
+			if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszFile, 0,
+				"Filename string") != PVRSRV_OK)
+			{
+				goto init_failed;
+			}
+		}
+
+		if(!gsDBGPdumpState.pszMsg)
+		{
+			if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszMsg, 0,
+				"Message string") != PVRSRV_OK)
+			{
+				goto init_failed;
+			}
+		}
+
+		if(!gsDBGPdumpState.pszScript)
+		{
+			if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszScript, 0,
+				"Script string") != PVRSRV_OK)
+			{
+				goto init_failed;
+			}
+		}
+
+		for(i=0; i < PDUMP_NUM_STREAMS; i++)
+		{
+			gsDBGPdumpState.psStream[i] = gpfnDbgDrv->pfnCreateStream(pszStreamName[i],
+														DEBUG_CAPMODE_FRAMED,
+														DEBUG_OUTMODE_STREAMENABLE,
+														0,
+														10);
+
+			gpfnDbgDrv->pfnSetCaptureMode(gsDBGPdumpState.psStream[i],DEBUG_CAPMODE_FRAMED,0xFFFFFFFF, 0xFFFFFFFF, 1);
+			gpfnDbgDrv->pfnSetFrame(gsDBGPdumpState.psStream[i],0);
+		}
+
+		PDUMPCOMMENT("Driver Product Name: %s", VS_PRODUCT_NAME);
+		PDUMPCOMMENT("Driver Product Version: %s (%s)", PVRVERSION_STRING, PVRVERSION_FILE);
+		PDUMPCOMMENT("Start of Init Phase");
+	}
+
+	return;
+
+init_failed:
+
+	if(gsDBGPdumpState.pszFile)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
+		gsDBGPdumpState.pszFile = IMG_NULL;
+	}
+
+	if(gsDBGPdumpState.pszScript)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
+		gsDBGPdumpState.pszScript = IMG_NULL;
+	}
+
+	if(gsDBGPdumpState.pszMsg)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
+		gsDBGPdumpState.pszMsg = IMG_NULL;
+	}
+
+	gpfnDbgDrv = IMG_NULL;
+}
+
+
+IMG_VOID PDumpDeInit(IMG_VOID)
+{
+	IMG_UINT32 i;
+
+	for(i=0; i < PDUMP_NUM_STREAMS; i++)
+	{
+		gpfnDbgDrv->pfnDestroyStream(gsDBGPdumpState.psStream[i]);
+	}
+
+	if(gsDBGPdumpState.pszFile)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
+		gsDBGPdumpState.pszFile = IMG_NULL;
+	}
+
+	if(gsDBGPdumpState.pszScript)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
+		gsDBGPdumpState.pszScript = IMG_NULL;
+	}
+
+	if(gsDBGPdumpState.pszMsg)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
+		gsDBGPdumpState.pszMsg = IMG_NULL;
+	}
+
+	gpfnDbgDrv = IMG_NULL;
+}
+
+PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID)
+{
+	IMG_UINT32 i;
+
+	if (gpfnDbgDrv)
+	{
+		PDUMPCOMMENT("Start Init Phase");
+		for(i=0; i < PDUMP_NUM_STREAMS; i++)
+		{
+			gpfnDbgDrv->pfnStartInitPhase(gsDBGPdumpState.psStream[i]);
+		}
+	}
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID)
+{
+	IMG_UINT32 i;
+
+	if (gpfnDbgDrv)
+	{
+		PDUMPCOMMENT("Stop Init Phase");
+
+		for(i=0; i < PDUMP_NUM_STREAMS; i++)
+		{
+			gpfnDbgDrv->pfnStopInitPhase(gsDBGPdumpState.psStream[i]);
+		}
+	}
+	return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID)
+{
+	return gpfnDbgDrv->pfnIsLastCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
+}
+
+
+IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID)
+{
+	if (PDumpSuspended())
+	{
+		return IMG_FALSE;
+	}
+	return gpfnDbgDrv->pfnIsCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], IMG_FALSE);
+}
+
+PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame)
+{
+	IMG_UINT32	ui32Stream;
+
+	for	(ui32Stream = 0; ui32Stream < PDUMP_NUM_STREAMS; ui32Stream++)
+	{
+		if	(gsDBGPdumpState.psStream[ui32Stream])
+		{
+			DbgSetFrame(gsDBGPdumpState.psStream[ui32Stream], ui32Frame);
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpGetFrameKM(IMG_PUINT32 pui32Frame)
+{
+	*pui32Frame = DbgGetFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
+
+	return PVRSRV_OK;
+}
+
+
+
+static IMG_BOOL PDumpWriteString2(IMG_CHAR * pszString, IMG_UINT32 ui32Flags)
+{
+	return PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], (IMG_UINT8 *) pszString, strlen(pszString), ui32Flags);
+}
+
+
+static IMG_BOOL PDumpWriteILock(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags)
+{
+	IMG_UINT32 ui32Written = 0;
+	IMG_UINT32 ui32Off = 0;
+
+	if ((psStream == IMG_NULL) || PDumpSuspended() || ((ui32Flags & PDUMP_FLAGS_NEVER) != 0))
+	{
+		return IMG_TRUE;
+	}
+
+
+
+
+	if (psStream == gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2])
+	{
+		IMG_UINT32 ui32ParamOutPos = gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2]);
+
+		if (ui32ParamOutPos + ui32Count > MAX_FILE_SIZE)
+		{
+			if ((gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2] && PDumpWriteString2("\r\n-- Splitting pdump output file\r\n\r\n", ui32Flags)))
+			{
+				DbgSetMarker(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2], ui32ParamOutPos);
+				gsDBGPdumpState.ui32ParamFileNum++;
+			}
+		}
+	}
+
+
+	while (((IMG_UINT32) ui32Count > 0) && (ui32Written != 0xFFFFFFFF))
+	{
+		ui32Written = DbgWrite(psStream, &pui8Data[ui32Off], ui32Count, ui32Flags);
+
+
+
+
+		if (ui32Written == 0)
+		{
+			OSReleaseThreadQuanta();
+		}
+
+		if (ui32Written != 0xFFFFFFFF)
+		{
+			ui32Off += ui32Written;
+			ui32Count -= ui32Written;
+		}
+	}
+
+	if (ui32Written == 0xFFFFFFFF)
+	{
+		return IMG_FALSE;
+	}
+
+	return IMG_TRUE;
+}
+
+static IMG_VOID DbgSetFrame(PDBG_STREAM psStream, IMG_UINT32 ui32Frame)
+{
+	gpfnDbgDrv->pfnSetFrame(psStream, ui32Frame);
+}
+
+
+static IMG_UINT32 DbgGetFrame(PDBG_STREAM psStream)
+{
+	return gpfnDbgDrv->pfnGetFrame(psStream);
+}
+
+static IMG_VOID DbgSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+	gpfnDbgDrv->pfnSetMarker(psStream, ui32Marker);
+}
+
+static IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags)
+{
+	IMG_UINT32	ui32BytesWritten;
+
+	if ((ui32Flags & PDUMP_FLAGS_CONTINUOUS) != 0)
+	{
+
+
+		if (((psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
+		    (psStream->ui32Start == 0xFFFFFFFFUL) &&
+		    (psStream->ui32End == 0xFFFFFFFFUL) &&
+		     psStream->bInitPhaseComplete)
+		{
+			ui32BytesWritten = ui32BCount;
+		}
+		else
+		{
+			ui32BytesWritten = gpfnDbgDrv->pfnDBGDrivWrite2(psStream, pui8Data, ui32BCount, 1);
+		}
+	}
+	else
+	{
+		if (ui32Flags & PDUMP_FLAGS_LASTFRAME)
+		{
+			IMG_UINT32	ui32DbgFlags;
+
+			ui32DbgFlags = 0;
+			if (ui32Flags & PDUMP_FLAGS_RESETLFBUFFER)
+			{
+				ui32DbgFlags |= WRITELF_FLAGS_RESETBUF;
+			}
+
+			ui32BytesWritten = gpfnDbgDrv->pfnWriteLF(psStream, pui8Data, ui32BCount, 1, ui32DbgFlags);
+		}
+		else
+		{
+			ui32BytesWritten = gpfnDbgDrv->pfnWriteBINCM(psStream, pui8Data, ui32BCount, 1);
+		}
+	}
+
+	return ui32BytesWritten;
+}
+
+
+IMG_VOID PDumpSuspendKM(IMG_VOID)
+{
+	atomic_inc(&gsPDumpSuspended);
+}
+
+IMG_VOID PDumpResumeKM(IMG_VOID)
+{
+	atomic_dec(&gsPDumpSuspended);
+}
+
+#endif
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/private_data.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/private_data.h
new file mode 100644
index 0000000..10a0201
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/private_data.h
@@ -0,0 +1,63 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __INCLUDED_PRIVATE_DATA_H_
+#define __INCLUDED_PRIVATE_DATA_H_
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include <linux/list.h>
+#include <drm/drmP.h>
+#endif
+
+typedef struct
+{
+
+	IMG_UINT32 ui32OpenPID;
+
+#if defined(PVR_SECURE_FD_EXPORT)
+
+	IMG_HANDLE hKernelMemInfo;
+#endif
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+
+	struct list_head sDRMAuthListItem;
+
+	struct drm_file *psDRMFile;
+#endif
+
+#if defined(SUPPORT_MEMINFO_IDS)
+
+	IMG_UINT64 ui64Stamp;
+#endif
+
+
+	IMG_HANDLE hBlockAlloc;
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+	IMG_PVOID pPriv;
+#endif
+}
+PVRSRV_FILE_PRIVATE_DATA;
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/proc.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/proc.c
new file mode 100644
index 0000000..50245a1
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/proc.c
@@ -0,0 +1,962 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include "services_headers.h"
+
+#include "queue.h"
+#include "resman.h"
+#include "pvrmmap.h"
+#include "pvr_debug.h"
+#include "pvrversion.h"
+#include "proc.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "linkage.h"
+
+#include "lists.h"
+DECLARE_LIST_ANY_VA(PVRSRV_DEVICE_NODE);
+
+
+static struct proc_dir_entry * dir;
+
+#ifndef PVR_PROC_USE_SEQ_FILE
+static off_t procDumpSysNodes(IMG_CHAR *buf, size_t size, off_t off);
+static off_t procDumpVersion(IMG_CHAR *buf, size_t size, off_t off);
+#endif
+
+
+static const IMG_CHAR PVRProcDirRoot[] = "pvr";
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+#define PVR_PROC_SEQ_START_TOKEN (void*)1
+static IMG_INT pvr_proc_open(struct inode *inode,struct file *file);
+static void *pvr_proc_seq_start (struct seq_file *m, loff_t *pos);
+static void pvr_proc_seq_stop (struct seq_file *m, void *v);
+static void *pvr_proc_seq_next (struct seq_file *m, void *v, loff_t *pos);
+static int pvr_proc_seq_show (struct seq_file *m, void *v);
+static ssize_t pvr_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
+
+static struct file_operations pvr_proc_operations =
+{
+	.open		= pvr_proc_open,
+	.read		= seq_read,
+	.write		= pvr_proc_write,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+static struct seq_operations pvr_proc_seq_operations =
+{
+	.start =	pvr_proc_seq_start,
+	.next =		pvr_proc_seq_next,
+	.stop =		pvr_proc_seq_stop,
+	.show =		pvr_proc_seq_show,
+};
+
+static struct proc_dir_entry* g_pProcQueue;
+static struct proc_dir_entry* g_pProcVersion;
+static struct proc_dir_entry* g_pProcSysNodes;
+
+#ifdef DEBUG
+static struct proc_dir_entry* g_pProcDebugLevel;
+#endif
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+static struct proc_dir_entry* g_pProcPowerLevel;
+#endif
+
+
+static void ProcSeqShowVersion(struct seq_file *sfile,void* el);
+
+static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off);
+
+#endif
+
+off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
+{
+    IMG_INT n;
+    size_t space = size - (size_t)off;
+    va_list ap;
+
+    PVR_ASSERT(space >= 0);
+
+    va_start (ap, format);
+
+    n = vsnprintf (buffer+off, space, format, ap);
+
+    va_end (ap);
+
+    if (n >= (IMG_INT)space || n < 0)
+    {
+
+        buffer[size - 1] = 0;
+        return (off_t)(size - 1);
+    }
+    else
+    {
+        return (off + (off_t)n);
+    }
+}
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off)
+{
+
+	if(!off)
+		return (void*)2;
+	return NULL;
+}
+
+
+void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off)
+{
+	if(!off)
+	{
+		return PVR_PROC_SEQ_START_TOKEN;
+	}
+
+
+	if(off == 1)
+		return (void*)2;
+
+	return NULL;
+}
+
+
+static IMG_INT pvr_proc_open(struct inode *inode,struct file *file)
+{
+	IMG_INT ret = seq_open(file, &pvr_proc_seq_operations);
+
+	struct seq_file *seq = (struct seq_file*)file->private_data;
+	struct proc_dir_entry* pvr_proc_entry = PDE(inode);
+
+
+	seq->private = pvr_proc_entry->data;
+	return ret;
+}
+
+static ssize_t pvr_proc_write(struct file *file, const char __user *buffer,
+		size_t count, loff_t *ppos)
+{
+	struct inode *inode = file->f_path.dentry->d_inode;
+	struct proc_dir_entry * dp;
+
+	dp = PDE(inode);
+
+	if (!dp->write_proc)
+		return -EIO;
+
+	return dp->write_proc(file, buffer, count, dp->data);
+}
+
+
+static void *pvr_proc_seq_start (struct seq_file *proc_seq_file, loff_t *pos)
+{
+	PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+	if(handlers->startstop != NULL)
+		handlers->startstop(proc_seq_file, IMG_TRUE);
+	return handlers->off2element(proc_seq_file, *pos);
+}
+
+static void pvr_proc_seq_stop (struct seq_file *proc_seq_file, void *v)
+{
+	PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+	if(handlers->startstop != NULL)
+		handlers->startstop(proc_seq_file, IMG_FALSE);
+}
+
+static void *pvr_proc_seq_next (struct seq_file *proc_seq_file, void *v, loff_t *pos)
+{
+	PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+	(*pos)++;
+	if( handlers->next != NULL)
+		return handlers->next( proc_seq_file, v, *pos );
+	return handlers->off2element(proc_seq_file, *pos);
+}
+
+static int pvr_proc_seq_show (struct seq_file *proc_seq_file, void *v)
+{
+	PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+	handlers->show( proc_seq_file,v );
+    return 0;
+}
+
+
+
+static struct proc_dir_entry* CreateProcEntryInDirSeq(
+									   struct proc_dir_entry *pdir,
+									   const IMG_CHAR * name,
+								   IMG_VOID* data,
+									   pvr_next_proc_seq_t next_handler,
+									   pvr_show_proc_seq_t show_handler,
+									   pvr_off2element_proc_seq_t off2element_handler,
+									   pvr_startstop_proc_seq_t startstop_handler,
+									   write_proc_t whandler
+									   )
+{
+
+    struct proc_dir_entry * file;
+	mode_t mode;
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
+        return NULL;
+    }
+
+	mode = S_IFREG;
+
+    if (show_handler)
+    {
+		mode |= S_IRUGO;
+    }
+
+    if (whandler)
+    {
+		mode |= S_IWUSR;
+    }
+
+	file=create_proc_entry(name, mode, pdir);
+
+    if (file)
+    {
+		PVR_PROC_SEQ_HANDLERS *seq_handlers;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+        file->owner = THIS_MODULE;
+#endif
+
+		file->proc_fops = &pvr_proc_operations;
+		file->write_proc = whandler;
+
+
+		file->data =  kmalloc(sizeof(PVR_PROC_SEQ_HANDLERS), GFP_KERNEL);
+		if(file->data)
+		{
+			seq_handlers = (PVR_PROC_SEQ_HANDLERS*)file->data;
+			seq_handlers->next = next_handler;
+			seq_handlers->show = show_handler;
+			seq_handlers->off2element = off2element_handler;
+			seq_handlers->startstop = startstop_handler;
+			seq_handlers->data = data;
+
+	return file;
+		}
+    }
+
+    PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
+    return 0;
+}
+
+
+struct proc_dir_entry* CreateProcReadEntrySeq (
+								const IMG_CHAR * name,
+								IMG_VOID* data,
+								pvr_next_proc_seq_t next_handler,
+								pvr_show_proc_seq_t show_handler,
+								pvr_off2element_proc_seq_t off2element_handler,
+								pvr_startstop_proc_seq_t startstop_handler
+							   )
+{
+	return CreateProcEntrySeq(name,
+							  data,
+							  next_handler,
+							  show_handler,
+							  off2element_handler,
+							  startstop_handler,
+							  NULL);
+}
+
+struct proc_dir_entry* CreateProcEntrySeq (
+											const IMG_CHAR * name,
+											IMG_VOID* data,
+											pvr_next_proc_seq_t next_handler,
+											pvr_show_proc_seq_t show_handler,
+											pvr_off2element_proc_seq_t off2element_handler,
+											pvr_startstop_proc_seq_t startstop_handler,
+											write_proc_t whandler
+										  )
+{
+	return CreateProcEntryInDirSeq(
+								   dir,
+								   name,
+								   data,
+								   next_handler,
+								   show_handler,
+								   off2element_handler,
+								   startstop_handler,
+								   NULL
+								  );
+}
+
+
+
+struct proc_dir_entry* CreatePerProcessProcEntrySeq (
+									  const IMG_CHAR * name,
+								  IMG_VOID* data,
+									  pvr_next_proc_seq_t next_handler,
+									  pvr_show_proc_seq_t show_handler,
+									  pvr_off2element_proc_seq_t off2element_handler,
+									  pvr_startstop_proc_seq_t startstop_handler,
+									  write_proc_t whandler
+									 )
+{
+    PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+    IMG_UINT32 ui32PID;
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: /proc/%s doesn't exist", PVRProcDirRoot));
+        return NULL;
+    }
+
+    ui32PID = OSGetCurrentProcessIDKM();
+
+    psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+    if (!psPerProc)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: no per process data"));
+
+        return NULL;
+    }
+
+    if (!psPerProc->psProcDir)
+    {
+        IMG_CHAR dirname[16];
+        IMG_INT ret;
+
+        ret = snprintf(dirname, sizeof(dirname), "%lu", ui32PID);
+
+		if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
+			return NULL;
+		}
+		else
+		{
+			psPerProc->psProcDir = proc_mkdir(dirname, dir);
+			if (!psPerProc->psProcDir)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't create per process proc directory /proc/%s/%u",
+						PVRProcDirRoot, ui32PID));
+				return NULL;
+			}
+		}
+    }
+
+    return CreateProcEntryInDirSeq(psPerProc->psProcDir, name, data, next_handler,
+								   show_handler,off2element_handler,startstop_handler,whandler);
+}
+
+
+IMG_VOID RemoveProcEntrySeq( struct proc_dir_entry* proc_entry )
+{
+    if (dir)
+    {
+		void* data = proc_entry->data ;
+        PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, proc_entry->name));
+
+        remove_proc_entry(proc_entry->name, dir);
+		if( data)
+			kfree( data );
+
+    }
+}
+
+IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry)
+{
+    PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+
+    psPerProc = LinuxTerminatingProcessPrivateData();
+    if (!psPerProc)
+    {
+        psPerProc = PVRSRVFindPerProcessPrivateData();
+        if (!psPerProc)
+        {
+            PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't "
+                                    "remove %s, no per process data", proc_entry->name));
+            return;
+        }
+    }
+
+    if (psPerProc->psProcDir)
+    {
+		void* data = proc_entry->data ;
+        PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", proc_entry->name, psPerProc->psProcDir->name));
+
+        remove_proc_entry(proc_entry->name, psPerProc->psProcDir);
+		if(data)
+			kfree( data );
+    }
+}
+
+#endif
+
+static IMG_INT pvr_read_proc(IMG_CHAR *page, IMG_CHAR **start, off_t off,
+                         IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+    pvr_read_proc_t *pprn = (pvr_read_proc_t *)data;
+
+    off_t len = pprn (page, (size_t)count, off);
+
+    if (len == END_OF_FILE)
+    {
+        len  = 0;
+        *eof = 1;
+    }
+    else if (!len)
+    {
+        *start = (IMG_CHAR *) 0;
+    }
+    else
+    {
+        *start = (IMG_CHAR *) 1;
+    }
+
+    return len;
+}
+
+
+static IMG_INT CreateProcEntryInDir(struct proc_dir_entry *pdir, const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+    struct proc_dir_entry * file;
+    mode_t mode;
+
+    if (!pdir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDir: parent directory doesn't exist"));
+
+        return -ENOMEM;
+    }
+
+    mode = S_IFREG;
+
+    if (rhandler)
+    {
+	mode |= S_IRUGO;
+    }
+
+    if (whandler)
+    {
+	mode |= S_IWUSR;
+    }
+
+    file = create_proc_entry(name, mode, pdir);
+
+    if (file)
+    {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+        file->owner = THIS_MODULE;
+#endif
+		file->read_proc = rhandler;
+		file->write_proc = whandler;
+		file->data = data;
+
+		PVR_DPF((PVR_DBG_MESSAGE, "Created proc entry %s in %s", name, pdir->name));
+
+        return 0;
+    }
+
+    PVR_DPF((PVR_DBG_ERROR, "CreateProcEntry: cannot create proc entry %s in %s", name, pdir->name));
+
+    return -ENOMEM;
+}
+
+
+IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+    return CreateProcEntryInDir(dir, name, rhandler, whandler, data);
+}
+
+
+IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+    PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+    IMG_UINT32 ui32PID;
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: /proc/%s doesn't exist", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+
+    ui32PID = OSGetCurrentProcessIDKM();
+
+    psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+    if (!psPerProc)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: no per process data"));
+
+        return -ENOMEM;
+    }
+
+    if (!psPerProc->psProcDir)
+    {
+        IMG_CHAR dirname[16];
+        IMG_INT ret;
+
+        ret = snprintf(dirname, sizeof(dirname), "%lu", ui32PID);
+
+		if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
+
+					return -ENOMEM;
+		}
+		else
+		{
+			psPerProc->psProcDir = proc_mkdir(dirname, dir);
+			if (!psPerProc->psProcDir)
+			{
+			PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't create per process proc directory /proc/%s/%u", PVRProcDirRoot, ui32PID));
+
+			return -ENOMEM;
+			}
+		}
+    }
+
+    return CreateProcEntryInDir(psPerProc->psProcDir, name, rhandler, whandler, data);
+}
+
+
+IMG_INT CreateProcReadEntry(const IMG_CHAR * name, pvr_read_proc_t handler)
+{
+    struct proc_dir_entry * file;
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
+
+        return -ENOMEM;
+    }
+
+    file = create_proc_read_entry (name, S_IFREG | S_IRUGO, dir, pvr_read_proc, (IMG_VOID *)handler);
+
+    if (file)
+    {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+        file->owner = THIS_MODULE;
+#endif
+        return 0;
+    }
+
+    PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
+
+    return -ENOMEM;
+}
+
+
+IMG_INT CreateProcEntries(IMG_VOID)
+{
+    dir = proc_mkdir (PVRProcDirRoot, NULL);
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: cannot make /proc/%s directory", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+	g_pProcQueue = CreateProcReadEntrySeq("queue", NULL, NULL, ProcSeqShowQueue, ProcSeqOff2ElementQueue, NULL);
+	g_pProcVersion = CreateProcReadEntrySeq("version", NULL, NULL, ProcSeqShowVersion, ProcSeq1ElementHeaderOff2Element, NULL);
+	g_pProcSysNodes = CreateProcReadEntrySeq("nodes", NULL, NULL, ProcSeqShowSysNodes, ProcSeqOff2ElementSysNodes, NULL);
+
+	if(!g_pProcQueue || !g_pProcVersion || !g_pProcSysNodes)
+#else
+    if (CreateProcReadEntry("queue", QueuePrintQueues) ||
+		CreateProcReadEntry("version", procDumpVersion) ||
+		CreateProcReadEntry("nodes", procDumpSysNodes))
+#endif
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s files", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+
+
+#ifdef DEBUG
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+	g_pProcDebugLevel = CreateProcEntrySeq("debug_level", NULL, NULL,
+											ProcSeqShowDebugLevel,
+											ProcSeq1ElementOff2Element, NULL,
+										    PVRDebugProcSetLevel);
+	if(!g_pProcDebugLevel)
+#else
+	if (CreateProcEntry ("debug_level", PVRDebugProcGetLevel, PVRDebugProcSetLevel, 0))
+#endif
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/debug_level", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+#ifdef PVR_PROC_USE_SEQ_FILE
+	g_pProcPowerLevel = CreateProcEntrySeq("power_control", NULL, NULL,
+											ProcSeqShowPowerLevel,
+											ProcSeq1ElementOff2Element, NULL,
+										    PVRProcSetPowerLevel);
+	if(!g_pProcPowerLevel)
+#else
+	if (CreateProcEntry("power_control", PVRProcGetPowerLevel, PVRProcSetPowerLevel, 0))
+#endif
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/power_control", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+#endif
+#endif
+
+    return 0;
+}
+
+
+IMG_VOID RemoveProcEntry(const IMG_CHAR * name)
+{
+    if (dir)
+    {
+        remove_proc_entry(name, dir);
+        PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, name));
+    }
+}
+
+
+IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR *name)
+{
+    PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+
+    psPerProc = LinuxTerminatingProcessPrivateData();
+    if (!psPerProc)
+    {
+        psPerProc = PVRSRVFindPerProcessPrivateData();
+        if (!psPerProc)
+        {
+            PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't "
+                                    "remove %s, no per process data", name));
+            return;
+        }
+    }
+
+    if (psPerProc->psProcDir)
+    {
+        remove_proc_entry(name, psPerProc->psProcDir);
+
+        PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", name, psPerProc->psProcDir->name));
+    }
+}
+
+
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
+{
+    if (psPerProc->psProcDir)
+    {
+        while (psPerProc->psProcDir->subdir)
+        {
+            PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s/%s", PVRProcDirRoot, psPerProc->psProcDir->name, psPerProc->psProcDir->subdir->name));
+
+            RemoveProcEntry(psPerProc->psProcDir->subdir->name);
+        }
+        RemoveProcEntry(psPerProc->psProcDir->name);
+    }
+}
+
+IMG_VOID RemoveProcEntries(IMG_VOID)
+{
+#ifdef DEBUG
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+    RemoveProcEntrySeq( g_pProcDebugLevel );
+#else
+    RemoveProcEntry("debug_level");
+#endif
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+#ifdef PVR_PROC_USE_SEQ_FILE
+    RemoveProcEntrySeq( g_pProcPowerLevel );
+#else
+    RemoveProcEntry("power_control");
+#endif
+#endif
+
+#endif
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+    RemoveProcEntrySeq(g_pProcQueue);
+    RemoveProcEntrySeq(g_pProcVersion);
+	RemoveProcEntrySeq(g_pProcSysNodes);
+#else
+    RemoveProcEntry("queue");
+    RemoveProcEntry("version");
+    RemoveProcEntry("nodes");
+#endif
+
+    while (dir->subdir)
+    {
+	PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s", PVRProcDirRoot, dir->subdir->name));
+
+	RemoveProcEntry(dir->subdir->name);
+    }
+
+    remove_proc_entry(PVRProcDirRoot, NULL);
+}
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void ProcSeqShowVersion(struct seq_file *sfile,void* el)
+{
+	SYS_DATA * psSysData;
+	IMG_CHAR *pszSystemVersionString = "None";
+
+	if(el == PVR_PROC_SEQ_START_TOKEN)
+	{
+		seq_printf( sfile,
+						"Version %s (%s) %s\n",
+						PVRVERSION_STRING,
+						PVR_BUILD_TYPE, PVR_BUILD_DIR);
+		return;
+	}
+
+    SysAcquireData(&psSysData);
+
+    if(psSysData->pszVersionString)
+	{
+	pszSystemVersionString = psSysData->pszVersionString;
+    }
+
+	seq_printf( sfile, "System Version String: %s\n", pszSystemVersionString);
+}
+
+#else
+
+static off_t procDumpVersion(IMG_CHAR *buf, size_t size, off_t off)
+{
+    SYS_DATA *psSysData;
+
+    if (off == 0)
+    {
+	return printAppend(buf, size, 0,
+						"Version %s (%s) %s\n",
+						PVRVERSION_STRING,
+						PVR_BUILD_TYPE, PVR_BUILD_DIR);
+    }
+
+    SysAcquireData(&psSysData)
+
+    if (off == 1)
+    {
+        IMG_CHAR *pszSystemVersionString = "None";
+
+        if(psSysData->pszVersionString)
+        {
+            pszSystemVersionString = psSysData->pszVersionString;
+        }
+
+        if(strlen(pszSystemVersionString)
+            + strlen("System Version String: \n")
+            + 1 > size)
+        {
+            return 0;
+        }
+        return printAppend(buf, size, 0,
+                            "System Version String: %s\n",
+                            pszSystemVersionString);
+    }
+
+    return END_OF_FILE;
+}
+
+#endif
+
+
+static const IMG_CHAR *deviceTypeToString(PVRSRV_DEVICE_TYPE deviceType)
+{
+    switch (deviceType)
+    {
+        default:
+        {
+            static IMG_CHAR text[10];
+
+            sprintf(text, "?%x", (IMG_UINT)deviceType);
+
+            return text;
+        }
+    }
+}
+
+
+static const IMG_CHAR *deviceClassToString(PVRSRV_DEVICE_CLASS deviceClass)
+{
+    switch (deviceClass)
+    {
+	case PVRSRV_DEVICE_CLASS_3D:
+	{
+	    return "3D";
+	}
+	case PVRSRV_DEVICE_CLASS_DISPLAY:
+	{
+	    return "display";
+	}
+	case PVRSRV_DEVICE_CLASS_BUFFER:
+	{
+	    return "buffer";
+	}
+	default:
+	{
+	    static IMG_CHAR text[10];
+
+	    sprintf(text, "?%x", (IMG_UINT)deviceClass);
+	    return text;
+	}
+    }
+}
+
+IMG_VOID* DecOffPsDev_AnyVaCb(PVRSRV_DEVICE_NODE *psNode, va_list va)
+{
+	off_t *pOff = va_arg(va, off_t*);
+	if (--(*pOff))
+	{
+		return IMG_NULL;
+	}
+	else
+	{
+		return psNode;
+	}
+}
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el)
+{
+	SYS_DATA * psSysData;
+    PVRSRV_DEVICE_NODE	*psDevNode = (PVRSRV_DEVICE_NODE*)el;
+
+	if(el == PVR_PROC_SEQ_START_TOKEN)
+	{
+		seq_printf( sfile,
+						"Registered nodes\n"
+						"Addr     Type     Class    Index Ref pvDev     Size Res\n");
+		return;
+	}
+
+    SysAcquireData(&psSysData);
+
+	seq_printf( sfile,
+				  "%p %-8s %-8s %4d  %2lu  %p  %3lu  %p\n",
+				  psDevNode,
+				  deviceTypeToString(psDevNode->sDevId.eDeviceType),
+				  deviceClassToString(psDevNode->sDevId.eDeviceClass),
+				  psDevNode->sDevId.eDeviceClass,
+				  psDevNode->ui32RefCount,
+				  psDevNode->pvDevice,
+				  psDevNode->ui32pvDeviceSize,
+				  psDevNode->hResManContext);
+
+}
+
+static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off)
+{
+    SYS_DATA *psSysData;
+    PVRSRV_DEVICE_NODE	*psDevNode;
+	if(!off)
+	{
+		return PVR_PROC_SEQ_START_TOKEN;
+	}
+
+    SysAcquireData(&psSysData);
+
+
+	psDevNode = (PVRSRV_DEVICE_NODE*)
+				List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+													DecOffPsDev_AnyVaCb,
+													&off);
+
+
+	return (void*)psDevNode;
+}
+
+#else
+
+static
+off_t procDumpSysNodes(IMG_CHAR *buf, size_t size, off_t off)
+{
+    SYS_DATA 			*psSysData;
+    PVRSRV_DEVICE_NODE	*psDevNode;
+    off_t				len;
+
+
+    if (size < 80)
+    {
+		return 0;
+    }
+
+    if (off == 0)
+    {
+		return printAppend(buf, size, 0,
+						"Registered nodes\n"
+						"Addr     Type     Class    Index Ref pvDev     Size Res\n");
+    }
+
+    SysAcquireData(&psSysData);
+
+
+	psDevNode = (PVRSRV_DEVICE_NODE*)
+				List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+													DecOffPsDev_AnyVaCb,
+													&off);
+
+    if (!psDevNode)
+    {
+		return END_OF_FILE;
+    }
+
+    len = printAppend(buf, size, 0,
+				  "%p %-8s %-8s %4d  %2lu  %p  %3lu  %p\n",
+				  psDevNode,
+				  deviceTypeToString(psDevNode->sDevId.eDeviceType),
+				  deviceClassToString(psDevNode->sDevId.eDeviceClass),
+				  psDevNode->sDevId.eDeviceClass,
+				  psDevNode->ui32RefCount,
+				  psDevNode->pvDevice,
+				  psDevNode->ui32pvDeviceSize,
+				  psDevNode->hResManContext);
+    return (len);
+}
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/proc.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/proc.h
new file mode 100644
index 0000000..7aa5424
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/proc.h
@@ -0,0 +1,111 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION 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 <asm/system.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#define END_OF_FILE (off_t) -1
+
+typedef off_t (pvr_read_proc_t)(IMG_CHAR *, size_t, off_t);
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+#define PVR_PROC_SEQ_START_TOKEN (void*)1
+typedef void* (pvr_next_proc_seq_t)(struct seq_file *,void*,loff_t);
+typedef void* (pvr_off2element_proc_seq_t)(struct seq_file *, loff_t);
+typedef void (pvr_show_proc_seq_t)(struct seq_file *,void*);
+typedef void (pvr_startstop_proc_seq_t)(struct seq_file *, IMG_BOOL start);
+
+typedef struct _PVR_PROC_SEQ_HANDLERS_ {
+	pvr_next_proc_seq_t *next;
+	pvr_show_proc_seq_t *show;
+	pvr_off2element_proc_seq_t *off2element;
+	pvr_startstop_proc_seq_t *startstop;
+	IMG_VOID *data;
+} PVR_PROC_SEQ_HANDLERS;
+
+
+void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off);
+
+void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off);
+
+
+#endif
+
+off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
+	__attribute__((format(printf, 4, 5)));
+
+IMG_INT CreateProcEntries(IMG_VOID);
+
+IMG_INT CreateProcReadEntry (const IMG_CHAR * name, pvr_read_proc_t handler);
+
+IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data);
+
+IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data);
+
+IMG_VOID RemoveProcEntry(const IMG_CHAR * name);
+
+IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR * name);
+
+IMG_VOID RemoveProcEntries(IMG_VOID);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+struct proc_dir_entry* CreateProcReadEntrySeq (
+								const IMG_CHAR* name,
+								IMG_VOID* data,
+								pvr_next_proc_seq_t next_handler,
+								pvr_show_proc_seq_t show_handler,
+								pvr_off2element_proc_seq_t off2element_handler,
+								pvr_startstop_proc_seq_t startstop_handler
+							   );
+
+struct proc_dir_entry* CreateProcEntrySeq (
+								const IMG_CHAR* name,
+								IMG_VOID* data,
+								pvr_next_proc_seq_t next_handler,
+								pvr_show_proc_seq_t show_handler,
+								pvr_off2element_proc_seq_t off2element_handler,
+								pvr_startstop_proc_seq_t startstop_handler,
+								write_proc_t whandler
+							   );
+
+struct proc_dir_entry* CreatePerProcessProcEntrySeq (
+								const IMG_CHAR* name,
+								IMG_VOID* data,
+								pvr_next_proc_seq_t next_handler,
+								pvr_show_proc_seq_t show_handler,
+								pvr_off2element_proc_seq_t off2element_handler,
+								pvr_startstop_proc_seq_t startstop_handler,
+								write_proc_t whandler
+							   );
+
+
+IMG_VOID RemoveProcEntrySeq(struct proc_dir_entry* proc_entry);
+IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry);
+
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_bridge_k.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_bridge_k.c
new file mode 100644
index 0000000..8342891
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_bridge_k.c
@@ -0,0 +1,647 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "img_defs.h"
+#include "services.h"
+#include "pvr_bridge.h"
+#include "perproc.h"
+#include "mutex.h"
+#include "sysconfig.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "private_data.h"
+#include "linkage.h"
+#include "pvr_bridge_km.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#include "pvr_drm.h"
+#if defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include "env_perproc.h"
+#endif
+#endif
+
+#if defined(SUPPORT_VGX)
+#include "vgx_bridge.h"
+#endif
+
+#if defined(SUPPORT_SGX)
+#include "sgx_bridge.h"
+#endif
+
+#include "bridged_pvr_bridge.h"
+
+#ifdef MODULE_TEST
+#include "pvr_test_bridge.h"
+#include "kern_test.h"
+#endif
+
+
+#if defined(SUPPORT_DRI_DRM)
+#define	PRIVATE_DATA(pFile) ((pFile)->driver_priv)
+#else
+#define	PRIVATE_DATA(pFile) ((pFile)->private_data)
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+static struct proc_dir_entry *g_ProcBridgeStats =0;
+static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementBridgeStats(struct seq_file * sfile, loff_t off);
+static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start);
+
+#else
+static off_t printLinuxBridgeStats(IMG_CHAR * buffer, size_t size, off_t off);
+#endif
+
+#endif
+
+extern struct mutex gPVRSRVLock;
+
+#if defined(SUPPORT_MEMINFO_IDS)
+static IMG_UINT64 ui64Stamp;
+#endif
+
+PVRSRV_ERROR
+LinuxBridgeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+	{
+		IMG_INT iStatus;
+#ifdef PVR_PROC_USE_SEQ_FILE
+		g_ProcBridgeStats = CreateProcReadEntrySeq(
+												  "bridge_stats",
+												  NULL,
+												  ProcSeqNextBridgeStats,
+												  ProcSeqShowBridgeStats,
+												  ProcSeqOff2ElementBridgeStats,
+												  ProcSeqStartstopBridgeStats
+						  						 );
+		iStatus = !g_ProcBridgeStats ? -1 : 0;
+#else
+		iStatus = CreateProcReadEntry("bridge_stats", printLinuxBridgeStats);
+#endif
+
+		if(iStatus!=0)
+		{
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		}
+	}
+#endif
+	return CommonBridgeInit();
+}
+
+IMG_VOID
+LinuxBridgeDeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+#ifdef PVR_PROC_USE_SEQ_FILE
+    RemoveProcEntrySeq(g_ProcBridgeStats);
+#else
+	RemoveProcEntry("bridge_stats");
+#endif
+#endif
+}
+
+#if defined(DEBUG_BRIDGE_KM)
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start)
+{
+	if(start)
+	{
+		mutex_lock(&gPVRSRVLock);
+	}
+	else
+	{
+		mutex_unlock(&gPVRSRVLock);
+	}
+}
+
+
+static void* ProcSeqOff2ElementBridgeStats(struct seq_file *sfile, loff_t off)
+{
+	if(!off)
+	{
+		return PVR_PROC_SEQ_START_TOKEN;
+	}
+
+	if(off > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
+	{
+		return (void*)0;
+	}
+
+
+	return (void*)&g_BridgeDispatchTable[off-1];
+}
+
+static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off)
+{
+	return ProcSeqOff2ElementBridgeStats(sfile,off);
+}
+
+
+static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el)
+{
+	PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry = (	PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY*)el;
+
+	if(el == PVR_PROC_SEQ_START_TOKEN)
+	{
+		seq_printf(sfile,
+						  "Total ioctl call count = %lu\n"
+						  "Total number of bytes copied via copy_from_user = %lu\n"
+						  "Total number of bytes copied via copy_to_user = %lu\n"
+						  "Total number of bytes copied via copy_*_user = %lu\n\n"
+						  "%-45s | %-40s | %10s | %20s | %10s\n",
+						  g_BridgeGlobalStats.ui32IOCTLCount,
+						  g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
+						  g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+						  g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+						  "Bridge Name",
+						  "Wrapper Function",
+						  "Call Count",
+						  "copy_from_user Bytes",
+						  "copy_to_user Bytes"
+						 );
+		return;
+	}
+
+	seq_printf(sfile,
+				   "%-45s   %-40s   %-10lu   %-20lu   %-10lu\n",
+				   psEntry->pszIOCName,
+				   psEntry->pszFunctionName,
+				   psEntry->ui32CallCount,
+				   psEntry->ui32CopyFromUserTotalBytes,
+				   psEntry->ui32CopyToUserTotalBytes);
+}
+
+#else
+
+static off_t
+printLinuxBridgeStats(IMG_CHAR * buffer, size_t count, off_t off)
+{
+	PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry;
+	off_t Ret;
+
+	mutex_lock(&gPVRSRVLock);
+
+	if(!off)
+	{
+		if(count < 500)
+		{
+			Ret = 0;
+			goto unlock_and_return;
+		}
+		Ret = printAppend(buffer, count, 0,
+						  "Total ioctl call count = %lu\n"
+						  "Total number of bytes copied via copy_from_user = %lu\n"
+						  "Total number of bytes copied via copy_to_user = %lu\n"
+						  "Total number of bytes copied via copy_*_user = %lu\n\n"
+						  "%-45s | %-40s | %10s | %20s | %10s\n",
+						  g_BridgeGlobalStats.ui32IOCTLCount,
+						  g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
+						  g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+						  g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+						  "Bridge Name",
+						  "Wrapper Function",
+						  "Call Count",
+						  "copy_from_user Bytes",
+						  "copy_to_user Bytes"
+						 );
+		goto unlock_and_return;
+	}
+
+	if(off > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
+	{
+		Ret = END_OF_FILE;
+		goto unlock_and_return;
+	}
+
+	if(count < 300)
+	{
+		Ret = 0;
+		goto unlock_and_return;
+	}
+
+	psEntry = &g_BridgeDispatchTable[off-1];
+	Ret =  printAppend(buffer, count, 0,
+					   "%-45s   %-40s   %-10lu   %-20lu   %-10lu\n",
+					   psEntry->pszIOCName,
+					   psEntry->pszFunctionName,
+					   psEntry->ui32CallCount,
+					   psEntry->ui32CopyFromUserTotalBytes,
+					   psEntry->ui32CopyToUserTotalBytes);
+
+unlock_and_return:
+	mutex_unlock(&gPVRSRVLock);
+	return Ret;
+}
+#endif
+#endif
+
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT
+PVRSRV_BridgeDispatchKM(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+#else
+IMG_INT32
+PVRSRV_BridgeDispatchKM(struct file *pFile, IMG_UINT unref__ ioctlCmd, IMG_UINT32 arg)
+#endif
+{
+	IMG_UINT32 cmd;
+#if !defined(SUPPORT_DRI_DRM)
+	PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+	PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
+#endif
+	PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM;
+	IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+	PVRSRV_PER_PROCESS_DATA *psPerProc;
+	IMG_INT err = -EFAULT;
+
+	mutex_lock(&gPVRSRVLock);
+
+#if defined(SUPPORT_DRI_DRM)
+	PVR_UNREFERENCED_PARAMETER(dev);
+
+	psBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+	PVR_ASSERT(psBridgePackageKM != IMG_NULL);
+#else
+	PVR_UNREFERENCED_PARAMETER(ioctlCmd);
+
+	psBridgePackageKM = &sBridgePackageKM;
+
+	if(!OSAccessOK(PVR_VERIFY_WRITE,
+				   psBridgePackageUM,
+				   sizeof(PVRSRV_BRIDGE_PACKAGE)))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments",
+				 __FUNCTION__));
+
+		goto unlock_and_return;
+	}
+
+
+	if(OSCopyFromUser(IMG_NULL,
+					  psBridgePackageKM,
+					  psBridgePackageUM,
+					  sizeof(PVRSRV_BRIDGE_PACKAGE))
+	  != PVRSRV_OK)
+	{
+		goto unlock_and_return;
+	}
+#endif
+
+	cmd = psBridgePackageKM->ui32BridgeID;
+
+#if defined(MODULE_TEST)
+	switch (cmd)
+	{
+		case PVRSRV_BRIDGE_SERVICES_TEST_MEM1:
+			{
+				PVRSRV_ERROR eError = MemTest1();
+				if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+				{
+					PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+					pReturn->eError = eError;
+				}
+			}
+			err = 0;
+			goto unlock_and_return;
+		case PVRSRV_BRIDGE_SERVICES_TEST_MEM2:
+			{
+				PVRSRV_ERROR eError = MemTest2();
+				if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+				{
+					PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+					pReturn->eError = eError;
+				}
+			}
+			err = 0;
+			goto unlock_and_return;
+
+		case PVRSRV_BRIDGE_SERVICES_TEST_RESOURCE:
+			{
+				PVRSRV_ERROR eError = ResourceTest();
+				if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+				{
+					PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+					pReturn->eError = eError;
+				}
+			}
+			err = 0;
+			goto unlock_and_return;
+
+		case PVRSRV_BRIDGE_SERVICES_TEST_EVENTOBJECT:
+			{
+				PVRSRV_ERROR eError = EventObjectTest();
+				if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+				{
+					PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+					pReturn->eError = eError;
+				}
+			}
+			err = 0;
+			goto unlock_and_return;
+
+		case PVRSRV_BRIDGE_SERVICES_TEST_MEMMAPPING:
+			{
+				PVRSRV_ERROR eError = MemMappingTest();
+				if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+				{
+					PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+					pReturn->eError = eError;
+				}
+			}
+			err = 0;
+			goto unlock_and_return;
+
+		case PVRSRV_BRIDGE_SERVICES_TEST_PROCESSID:
+			{
+				PVRSRV_ERROR eError = ProcessIDTest();
+				if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+				{
+					PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+					pReturn->eError = eError;
+				}
+			}
+			err = 0;
+			goto unlock_and_return;
+
+		case PVRSRV_BRIDGE_SERVICES_TEST_CLOCKUSWAITUS:
+			{
+				PVRSRV_ERROR eError = ClockusWaitusTest();
+				if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+				{
+					PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+					pReturn->eError = eError;
+				}
+			}
+			err = 0;
+			goto unlock_and_return;
+
+		case PVRSRV_BRIDGE_SERVICES_TEST_TIMER:
+			{
+				PVRSRV_ERROR eError = TimerTest();
+				if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+				{
+					PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+					pReturn->eError = eError;
+				}
+			}
+			err = 0;
+			goto unlock_and_return;
+
+		case PVRSRV_BRIDGE_SERVICES_TEST_PRIVSRV:
+			{
+				PVRSRV_ERROR eError = PrivSrvTest();
+				if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+				{
+					PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+					pReturn->eError = eError;
+				}
+			}
+			err = 0;
+			goto unlock_and_return;
+		case PVRSRV_BRIDGE_SERVICES_TEST_COPYDATA:
+		{
+			IMG_UINT32               ui32PID;
+			PVRSRV_PER_PROCESS_DATA *psPerProc;
+			PVRSRV_ERROR eError;
+
+			ui32PID = OSGetCurrentProcessIDKM();
+
+			PVRSRVTrace("PVRSRV_BRIDGE_SERVICES_TEST_COPYDATA %d", ui32PID);
+
+			psPerProc = PVRSRVPerProcessData(ui32PID);
+
+			eError = CopyDataTest(psBridgePackageKM->pvParamIn, psBridgePackageKM->pvParamOut, psPerProc);
+
+			*(PVRSRV_ERROR*)psBridgePackageKM->pvParamOut = eError;
+			err = 0;
+			goto unlock_and_return;
+		}
+
+
+		case PVRSRV_BRIDGE_SERVICES_TEST_POWERMGMT:
+			{
+				PVRSRV_ERROR eError = PowerMgmtTest();
+				if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+				{
+					PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+					pReturn->eError = eError;
+				}
+			}
+			err = 0;
+			goto unlock_and_return;
+
+	}
+#endif
+
+	if(cmd != PVRSRV_BRIDGE_CONNECT_SERVICES)
+	{
+		PVRSRV_ERROR eError;
+
+		eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+									(IMG_PVOID *)&psPerProc,
+									psBridgePackageKM->hKernelServices,
+									PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Invalid kernel services handle (%d)",
+					 __FUNCTION__, eError));
+			goto unlock_and_return;
+		}
+
+		if(psPerProc->ui32PID != ui32PID)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Process %d tried to access data "
+					 "belonging to process %d", __FUNCTION__, ui32PID,
+					 psPerProc->ui32PID));
+			goto unlock_and_return;
+		}
+	}
+	else
+	{
+
+		psPerProc = PVRSRVPerProcessData(ui32PID);
+		if(psPerProc == IMG_NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BridgeDispatchKM: "
+					 "Couldn't create per-process data area"));
+			goto unlock_and_return;
+		}
+	}
+
+	psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID);
+
+#if defined(PVR_SECURE_FD_EXPORT)
+	switch(cmd)
+	{
+		case PVRSRV_BRIDGE_EXPORT_DEVICEMEM:
+		{
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+			if(psPrivateData->hKernelMemInfo)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Can only export one MemInfo "
+						 "per file descriptor", __FUNCTION__));
+				err = -EINVAL;
+				goto unlock_and_return;
+			}
+			break;
+		}
+
+		case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+		{
+			PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN =
+				(PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamIn;
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+			if(!psPrivateData->hKernelMemInfo)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: File descriptor has no "
+						 "associated MemInfo handle", __FUNCTION__));
+				err = -EINVAL;
+				goto unlock_and_return;
+			}
+
+			psMapDevMemIN->hKernelMemInfo = psPrivateData->hKernelMemInfo;
+			break;
+		}
+
+		default:
+		{
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+			if(psPrivateData->hKernelMemInfo)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Import/Export handle tried "
+						 "to use privileged service", __FUNCTION__));
+				goto unlock_and_return;
+			}
+			break;
+		}
+	}
+#endif
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+	switch(cmd)
+	{
+		case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+		case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+		{
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+			int authenticated = pFile->authenticated;
+			PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+			if (authenticated)
+			{
+				break;
+			}
+
+
+			psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)PVRSRVProcessPrivateData(psPerProc);
+			if (psEnvPerProc == IMG_NULL)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Process private data not allocated", __FUNCTION__));
+				err = -EFAULT;
+				goto unlock_and_return;
+			}
+
+			list_for_each_entry(psPrivateData, &psEnvPerProc->sDRMAuthListHead, sDRMAuthListItem)
+			{
+				struct drm_file *psDRMFile = psPrivateData->psDRMFile;
+
+				if (pFile->master == psDRMFile->master)
+				{
+					authenticated |= psDRMFile->authenticated;
+					if (authenticated)
+					{
+						break;
+					}
+				}
+			}
+
+			if (!authenticated)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Not authenticated for mapping device or device class memory", __FUNCTION__));
+				err = -EPERM;
+				goto unlock_and_return;
+			}
+			break;
+		}
+		default:
+			break;
+	}
+#endif
+
+	err = BridgedDispatchKM(psPerProc, psBridgePackageKM);
+	if(err != PVRSRV_OK)
+		goto unlock_and_return;
+
+	switch(cmd)
+	{
+#if defined(PVR_SECURE_FD_EXPORT)
+		case PVRSRV_BRIDGE_EXPORT_DEVICEMEM:
+		{
+			PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT =
+				(PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *)psBridgePackageKM->pvParamOut;
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+			psPrivateData->hKernelMemInfo = psExportDeviceMemOUT->hMemInfo;
+#if defined(SUPPORT_MEMINFO_IDS)
+			psExportDeviceMemOUT->ui64Stamp = psPrivateData->ui64Stamp = ++ui64Stamp;
+#endif
+			break;
+		}
+#endif
+
+#if defined(SUPPORT_MEMINFO_IDS)
+		case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+		{
+			PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDeviceMemoryOUT =
+				(PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamOut;
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+			psMapDeviceMemoryOUT->sDstClientMemInfo.ui64Stamp =	psPrivateData->ui64Stamp;
+			break;
+		}
+
+		case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+		{
+			PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psDeviceClassMemoryOUT =
+				(PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *)psBridgePackageKM->pvParamOut;
+			psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp = ++ui64Stamp;
+			break;
+		}
+#endif
+
+		default:
+			break;
+	}
+
+unlock_and_return:
+	mutex_unlock(&gPVRSRVLock);
+	return err;
+}
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_debug.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_debug.c
new file mode 100644
index 0000000..56d1046
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_debug.c
@@ -0,0 +1,418 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/hardirq.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/tty.h>
+#include <stdarg.h>
+#include "img_types.h"
+#include "servicesext.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "mutex.h"
+#include "linkage.h"
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+#define PVR_MAX_FILEPATH_LEN 256
+
+static IMG_UINT32 gPVRDebugLevel = DBGPRIV_WARNING;
+
+#endif
+
+#define	PVR_MAX_MSG_LEN PVR_MAX_DEBUG_MESSAGE_LEN
+
+static IMG_CHAR gszBufferNonIRQ[PVR_MAX_MSG_LEN + 1];
+
+static IMG_CHAR gszBufferIRQ[PVR_MAX_MSG_LEN + 1];
+
+static struct mutex gsDebugMutexNonIRQ;
+
+DEFINE_SPINLOCK(gsDebugLockIRQ);
+
+#define	USE_SPIN_LOCK (in_interrupt() || !preemptible())
+
+static inline void GetBufferLock(unsigned long *pulLockFlags)
+{
+	if (USE_SPIN_LOCK)
+	{
+		spin_lock_irqsave(&gsDebugLockIRQ, *pulLockFlags);
+	}
+	else
+	{
+		mutex_lock(&gsDebugMutexNonIRQ);
+	}
+}
+
+static inline void ReleaseBufferLock(unsigned long ulLockFlags)
+{
+	if (USE_SPIN_LOCK)
+	{
+		spin_unlock_irqrestore(&gsDebugLockIRQ, ulLockFlags);
+	}
+	else
+	{
+		mutex_unlock(&gsDebugMutexNonIRQ);
+	}
+}
+
+static inline void SelectBuffer(IMG_CHAR **ppszBuf, IMG_UINT32 *pui32BufSiz)
+{
+	if (USE_SPIN_LOCK)
+	{
+		*ppszBuf = gszBufferIRQ;
+		*pui32BufSiz = sizeof(gszBufferIRQ);
+	}
+	else
+	{
+		*ppszBuf = gszBufferNonIRQ;
+		*pui32BufSiz = sizeof(gszBufferNonIRQ);
+	}
+}
+
+static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR* pszFormat, va_list VArgs)
+{
+	IMG_UINT32 ui32Used;
+	IMG_UINT32 ui32Space;
+	IMG_INT32 i32Len;
+
+	ui32Used = strlen(pszBuf);
+	BUG_ON(ui32Used >= ui32BufSiz);
+	ui32Space = ui32BufSiz - ui32Used;
+
+	i32Len = vsnprintf(&pszBuf[ui32Used], ui32Space, pszFormat, VArgs);
+	pszBuf[ui32BufSiz - 1] = 0;
+
+
+	return (i32Len < 0 || i32Len >= ui32Space);
+}
+
+IMG_VOID PVRDPFInit(IMG_VOID)
+{
+    mutex_init(&gsDebugMutexNonIRQ);
+}
+
+IMG_VOID PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...)
+{
+	va_list vaArgs;
+	unsigned long ulLockFlags = 0;
+	IMG_CHAR *pszBuf;
+	IMG_UINT32 ui32BufSiz;
+
+	SelectBuffer(&pszBuf, &ui32BufSiz);
+
+	va_start(vaArgs, pszFormat);
+
+	GetBufferLock(&ulLockFlags);
+	strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+
+	if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+	{
+		printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+	}
+	else
+	{
+		printk(KERN_INFO "%s\n", pszBuf);
+	}
+
+	ReleaseBufferLock(ulLockFlags);
+	va_end(vaArgs);
+
+}
+
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+
+IMG_VOID PVRSRVDebugAssertFail(const IMG_CHAR* pszFile, IMG_UINT32 uLine)
+{
+	PVRSRVDebugPrintf(DBGPRIV_FATAL, pszFile, uLine, "Debug assertion failed!");
+	BUG();
+}
+
+#endif
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+
+IMG_VOID PVRSRVTrace(const IMG_CHAR* pszFormat, ...)
+{
+	va_list VArgs;
+	unsigned long ulLockFlags = 0;
+	IMG_CHAR *pszBuf;
+	IMG_UINT32 ui32BufSiz;
+
+	SelectBuffer(&pszBuf, &ui32BufSiz);
+
+	va_start(VArgs, pszFormat);
+
+	GetBufferLock(&ulLockFlags);
+
+	strncpy(pszBuf, "PVR: ", (ui32BufSiz -1));
+
+	if (VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs))
+	{
+		printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+	}
+	else
+	{
+		printk(KERN_INFO "%s\n", pszBuf);
+	}
+
+	ReleaseBufferLock(ulLockFlags);
+
+	va_end(VArgs);
+}
+
+#endif
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR *pszFormat, ...)
+{
+		va_list VArgs;
+		IMG_BOOL bTrunc;
+
+		va_start (VArgs, pszFormat);
+
+		bTrunc = VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs);
+
+		va_end (VArgs);
+
+		return bTrunc;
+}
+
+IMG_VOID PVRSRVDebugPrintf	(
+						IMG_UINT32	ui32DebugLevel,
+						const IMG_CHAR*	pszFullFileName,
+						IMG_UINT32	ui32Line,
+						const IMG_CHAR*	pszFormat,
+						...
+					)
+{
+	IMG_BOOL bTrace, bDebug;
+	const IMG_CHAR *pszFileName = pszFullFileName;
+	IMG_CHAR *pszLeafName;
+
+	bTrace = gPVRDebugLevel & ui32DebugLevel & DBGPRIV_CALLTRACE;
+	bDebug = ((gPVRDebugLevel & DBGPRIV_ALLLEVELS) >= ui32DebugLevel);
+
+	if (bTrace || bDebug)
+	{
+		va_list vaArgs;
+		unsigned long ulLockFlags = 0;
+		IMG_CHAR *pszBuf;
+		IMG_UINT32 ui32BufSiz;
+
+		SelectBuffer(&pszBuf, &ui32BufSiz);
+
+		va_start(vaArgs, pszFormat);
+
+		GetBufferLock(&ulLockFlags);
+
+
+		if (bDebug)
+		{
+			switch(ui32DebugLevel)
+			{
+				case DBGPRIV_FATAL:
+				{
+					strncpy (pszBuf, "PVR_K:(Fatal): ", (ui32BufSiz -1));
+					break;
+				}
+				case DBGPRIV_ERROR:
+				{
+					strncpy (pszBuf, "PVR_K:(Error): ", (ui32BufSiz -1));
+					break;
+				}
+				case DBGPRIV_WARNING:
+				{
+					strncpy (pszBuf, "PVR_K:(Warning): ", (ui32BufSiz -1));
+					break;
+				}
+				case DBGPRIV_MESSAGE:
+				{
+					strncpy (pszBuf, "PVR_K:(Message): ", (ui32BufSiz -1));
+					break;
+				}
+				case DBGPRIV_VERBOSE:
+				{
+					strncpy (pszBuf, "PVR_K:(Verbose): ", (ui32BufSiz -1));
+					break;
+				}
+				default:
+				{
+					strncpy (pszBuf, "PVR_K:(Unknown message level)", (ui32BufSiz -1));
+					break;
+				}
+			}
+		}
+		else
+		{
+			strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+		}
+
+		if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+		{
+			printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+		}
+		else
+		{
+
+			if (!bTrace)
+			{
+#ifdef DEBUG_LOG_PATH_TRUNCATE
+
+				static IMG_CHAR szFileNameRewrite[PVR_MAX_FILEPATH_LEN];
+
+				IMG_CHAR* pszTruncIter;
+				IMG_CHAR* pszTruncBackInter;
+
+
+				pszFileName = pszFullFileName + strlen(DEBUG_LOG_PATH_TRUNCATE)+1;
+
+
+				strncpy(szFileNameRewrite, pszFileName,PVR_MAX_FILEPATH_LEN);
+
+				if(strlen(szFileNameRewrite) == PVR_MAX_FILEPATH_LEN-1) {
+					IMG_CHAR szTruncateMassage[] = "FILENAME TRUNCATED";
+					strcpy(szFileNameRewrite + (PVR_MAX_FILEPATH_LEN - 1 - strlen(szTruncateMassage)), szTruncateMassage);
+				}
+
+				pszTruncIter = szFileNameRewrite;
+				while(*pszTruncIter++ != 0)
+				{
+					IMG_CHAR* pszNextStartPoint;
+
+					if(
+					   !( ( *pszTruncIter == '/' && (pszTruncIter-4 >= szFileNameRewrite) ) &&
+						 ( *(pszTruncIter-1) == '.') &&
+						 ( *(pszTruncIter-2) == '.') &&
+						 ( *(pszTruncIter-3) == '/') )
+					   ) continue;
+
+
+					pszTruncBackInter = pszTruncIter - 3;
+					while(*(--pszTruncBackInter) != '/')
+					{
+						if(pszTruncBackInter <= szFileNameRewrite) break;
+					}
+					pszNextStartPoint = pszTruncBackInter;
+
+
+					while(*pszTruncIter != 0)
+					{
+						*pszTruncBackInter++ = *pszTruncIter++;
+					}
+					*pszTruncBackInter = 0;
+
+
+					pszTruncIter = pszNextStartPoint;
+				}
+
+				pszFileName = szFileNameRewrite;
+
+				if(*pszFileName == '/') pszFileName++;
+#endif
+
+#if !defined(__sh__)
+				pszLeafName = (IMG_CHAR *)strrchr (pszFileName, '\\');
+
+				if (pszLeafName)
+				{
+					pszFileName = pszLeafName;
+		       	}
+#endif
+
+				if (BAppend(pszBuf, ui32BufSiz, " [%lu, %s]", ui32Line, pszFileName))
+				{
+					printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+				}
+				else
+				{
+					printk(KERN_INFO "%s\n", pszBuf);
+				}
+			}
+			else
+			{
+				printk(KERN_INFO "%s\n", pszBuf);
+			}
+		}
+
+		ReleaseBufferLock(ulLockFlags);
+
+		va_end (vaArgs);
+	}
+}
+
+#endif
+
+#if defined(DEBUG)
+
+IMG_VOID PVRDebugSetLevel(IMG_UINT32 uDebugLevel)
+{
+	printk(KERN_INFO "PVR: Setting Debug Level = 0x%x\n",(IMG_UINT)uDebugLevel);
+
+	gPVRDebugLevel = uDebugLevel;
+}
+
+IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
+{
+#define	_PROC_SET_BUFFER_SZ		2
+	IMG_CHAR data_buffer[_PROC_SET_BUFFER_SZ];
+
+	if (count != _PROC_SET_BUFFER_SZ)
+	{
+		return -EINVAL;
+	}
+	else
+	{
+		if (copy_from_user(data_buffer, buffer, count))
+			return -EINVAL;
+		if (data_buffer[count - 1] != '\n')
+			return -EINVAL;
+		PVRDebugSetLevel(data_buffer[0] - '0');
+	}
+	return (count);
+}
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el)
+{
+	seq_printf(sfile, "%lu\n", gPVRDebugLevel);
+}
+
+#else
+IMG_INT PVRDebugProcGetLevel(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+	if (off == 0) {
+		*start = (IMG_CHAR *)1;
+		return printAppend(page, count, 0, "%lu\n", gPVRDebugLevel);
+	}
+	*eof = 1;
+	return 0;
+}
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_drm.c b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_drm.c
new file mode 100644
index 0000000..f31f989
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_drm.c
@@ -0,0 +1,301 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if defined(SUPPORT_DRI_DRM)
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <asm/ioctl.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "kerneldisplay.h"
+#include "kernelbuffer.h"
+#include "sysconfig.h"
+#include "pvrmmap.h"
+#include "mm.h"
+#include "mmap.h"
+#include "mutex.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "perproc.h"
+#include "handle.h"
+#include "pvr_bridge_km.h"
+#include "pvr_bridge.h"
+#include "proc.h"
+#include "pvrversion.h"
+#include "linkage.h"
+#include "pvr_drm_shared.h"
+#include "pvr_drm.h"
+
+#define	MAKENAME_HELPER(x, y) x ## y
+#define	MAKENAME(x, y) MAKENAME_HELPER(x, y)
+
+#define PVR_DRM_NAME	"pvrsrvkm"
+#define PVR_DRM_DESC	"Imagination Technologies PVR DRM"
+
+#define PVR_PCI_IDS \
+	{SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0, 0, 0}
+
+struct pci_dev *gpsPVRLDMDev;
+struct drm_device *gpsPVRDRMDev;
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24))
+#error "Linux kernel version 2.6.25 or later required for PVR DRM support"
+#endif
+
+#define PVR_DRM_FILE struct drm_file *
+
+#if defined(DISPLAY_CONTROLLER)
+extern int MAKENAME(DISPLAY_CONTROLLER, _Init)(struct drm_device *);
+extern void MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(struct drm_device *);
+#endif
+
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+static struct pci_device_id asPciIdList[] = {
+	PVR_PCI_IDS
+};
+#endif
+
+IMG_INT PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags)
+{
+	IMG_INT iRes;
+
+	PVR_TRACE(("PVRSRVDrmLoad"));
+
+	gpsPVRDRMDev = dev;
+	gpsPVRLDMDev = dev->pdev;
+
+#if defined(PDUMP)
+	iRes = dbgdrv_init();
+	if (iRes != 0)
+	{
+		return iRes;
+	}
+#endif
+
+	iRes = PVRCore_Init();
+	if (iRes != 0)
+	{
+		goto exit_dbgdrv_cleanup;
+	}
+
+#if defined(DISPLAY_CONTROLLER)
+	iRes = MAKENAME(DISPLAY_CONTROLLER, _Init)(dev);
+	if (iRes != 0)
+	{
+		goto exit_pvrcore_cleanup;
+	}
+#endif
+	return 0;
+
+#if defined(DISPLAY_CONTROLLER)
+exit_pvrcore_cleanup:
+	PVRCore_Cleanup();
+#endif
+exit_dbgdrv_cleanup:
+#if defined(PDUMP)
+	dbgdrv_cleanup();
+#endif
+	return iRes;
+}
+
+IMG_INT PVRSRVDrmUnload(struct drm_device *dev)
+{
+	PVR_TRACE(("PVRSRVDrmUnload"));
+
+#if defined(DISPLAY_CONTROLLER)
+	MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(dev);
+#endif
+
+	PVRCore_Cleanup();
+
+#if defined(PDUMP)
+	dbgdrv_cleanup();
+#endif
+
+	return 0;
+}
+
+IMG_INT PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file)
+{
+	return PVRSRVOpen(dev, file);
+}
+
+IMG_VOID PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file)
+{
+	PVRSRVRelease(dev, file);
+}
+
+DRI_DRM_STATIC IMG_INT
+PVRDRMIsMaster(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+	return 0;
+}
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+IMG_INT
+PVRDRM_Dummy_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+	return 0;
+}
+#endif
+
+static IMG_INT
+PVRDRMPCIBusIDField(struct drm_device *dev, IMG_UINT32 *pui32Field, IMG_UINT32 ui32FieldType)
+{
+	struct pci_dev *psPCIDev = (struct pci_dev *)dev->pdev;
+
+	switch (ui32FieldType)
+	{
+		case PVR_DRM_PCI_DOMAIN:
+			*pui32Field = pci_domain_nr(psPCIDev->bus);
+			break;
+
+		case PVR_DRM_PCI_BUS:
+			*pui32Field = psPCIDev->bus->number;
+			break;
+
+		case PVR_DRM_PCI_DEV:
+			*pui32Field = PCI_SLOT(psPCIDev->devfn);
+			break;
+
+		case PVR_DRM_PCI_FUNC:
+			*pui32Field = PCI_FUNC(psPCIDev->devfn);
+			break;
+
+		default:
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+DRI_DRM_STATIC IMG_INT
+PVRDRMUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+	IMG_UINT32 *pui32Args = (IMG_UINT32 *)arg;
+	IMG_UINT32 ui32Cmd = pui32Args[0];
+	IMG_UINT32 ui32Arg1 = pui32Args[1];
+	IMG_UINT32 *pui32OutArg = (IMG_UINT32 *)arg;
+
+	switch (ui32Cmd)
+	{
+		case PVR_DRM_UNPRIV_INIT_SUCCESFUL:
+			*pui32OutArg = PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL) ? 1 : 0;
+			break;
+
+		case PVR_DRM_UNPRIV_BUSID_TYPE:
+			*pui32OutArg = PVR_DRM_BUS_TYPE_PCI;
+			break;
+
+		case PVR_DRM_UNPRIV_BUSID_FIELD:
+			return PVRDRMPCIBusIDField(dev, pui32OutArg, ui32Arg1);
+
+		default:
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+struct drm_ioctl_desc sPVRDrmIoctls[] = {
+	DRM_IOCTL_DEF(PVR_DRM_SRVKM_IOCTL, PVRSRV_BridgeDispatchKM, 0),
+	DRM_IOCTL_DEF(PVR_DRM_IS_MASTER_IOCTL, PVRDRMIsMaster, DRM_MASTER),
+	DRM_IOCTL_DEF(PVR_DRM_UNPRIV_IOCTL, PVRDRMUnprivCmd, 0),
+#if defined(PDUMP)
+	DRM_IOCTL_DEF(PVR_DRM_DBGDRV_IOCTL, dbgdrv_ioctl, 0),
+#endif
+};
+
+static IMG_INT pvr_max_ioctl = DRM_ARRAY_SIZE(sPVRDrmIoctls);
+
+static struct drm_driver sPVRDrmDriver =
+{
+	.driver_features = 0,
+	.dev_priv_size = 0,
+	.load = PVRSRVDrmLoad,
+	.unload = PVRSRVDrmUnload,
+	.open = PVRSRVDrmOpen,
+	.postclose = PVRSRVDrmPostClose,
+	.suspend = PVRSRVDriverSuspend,
+	.resume = PVRSRVDriverResume,
+	.get_map_ofs = drm_core_get_map_ofs,
+	.get_reg_ofs = drm_core_get_reg_ofs,
+	.ioctls = sPVRDrmIoctls,
+	.fops =
+	{
+		.owner = THIS_MODULE,
+		.open = drm_open,
+		.release = drm_release,
+		.ioctl = drm_ioctl,
+		.mmap = PVRMMap,
+		.poll = drm_poll,
+		.fasync = drm_fasync,
+	},
+	.pci_driver =
+	{
+		.name = PVR_DRM_NAME,
+		.id_table = asPciIdList,
+	},
+
+	.name = PVR_DRM_NAME,
+	.desc = PVR_DRM_DESC,
+	.date = PVR_BUILD_DATE,
+	.major = PVRVERSION_MAJ,
+	.minor = PVRVERSION_MIN,
+	.patchlevel = PVRVERSION_BUILD,
+};
+
+static IMG_INT __init PVRSRVDrmInit(IMG_VOID)
+{
+	IMG_INT iRes;
+	sPVRDrmDriver.num_ioctls = pvr_max_ioctl;
+
+
+	PVRDPFInit();
+
+	iRes = drm_init(&sPVRDrmDriver);
+
+	return iRes;
+}
+
+static IMG_VOID __exit PVRSRVDrmExit(IMG_VOID)
+{
+	drm_exit(&sPVRDrmDriver);
+}
+
+module_init(PVRSRVDrmInit);
+module_exit(PVRSRVDrmExit);
+#endif
+#endif
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_drm.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_drm.h
new file mode 100644
index 0000000..9f5e931
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/env/linux/pvr_drm.h
@@ -0,0 +1,65 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__PVR_DRM_H__)
+#define __PVR_DRM_H__
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRCore_Init(IMG_VOID);
+IMG_VOID PVRCore_Cleanup(IMG_VOID);
+IMG_INT PVRSRVOpen(struct drm_device *dev, struct drm_file *pFile);
+IMG_INT PVRSRVRelease(struct drm_device *dev, struct drm_file *pFile);
+IMG_INT PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state);
+IMG_INT PVRSRVDriverResume(struct drm_device *pDevice);
+
+IMG_INT PVRSRV_BridgeDispatchKM(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+#define	DRI_DRM_STATIC
+IMG_INT PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags);
+IMG_INT PVRSRVDrmUnload(struct drm_device *dev);
+IMG_VOID PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file);
+IMG_INT PVRDRMIsMaster(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+IMG_INT PVRDRMUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+IMG_INT PVRDRM_Dummy_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#else
+#define	DRI_DRM_STATIC	static
+#endif
+
+#if defined(PDUMP)
+int dbgdrv_init(void);
+void dbgdrv_cleanup(void);
+IMG_INT dbgdrv_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#endif
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+#define	PVR_DRM_SRVKM_IOCTL	_IO(0, PVR_DRM_SRVKM_CMD)
+#define	PVR_DRM_IS_MASTER_IOCTL _IO(0, PVR_DRM_IS_MASTER_CMD)
+#define	PVR_DRM_UNPRIV_IOCTL	_IO(0, PVR_DRM_UNPRIV_CMD)
+#define	PVR_DRM_DBGDRV_IOCTL	_IO(0, PVR_DRM_DBGDRV_CMD)
+#endif
+
+#endif
+
+#endif
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx535defs.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx535defs.h
new file mode 100644
index 0000000..4e1c97f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx535defs.h
@@ -0,0 +1,633 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _SGX535DEFS_KM_H_
+#define _SGX535DEFS_KM_H_
+
+#define EUR_CR_CLKGATECTL                   0x0000
+#define EUR_CR_CLKGATECTL_2D_CLKG_MASK      0x00000003UL
+#define EUR_CR_CLKGATECTL_2D_CLKG_SHIFT     0
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK     0x00000030UL
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT    4
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK     0x00000300UL
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT    8
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK      0x00003000UL
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT     12
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK     0x00030000UL
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT    16
+#define EUR_CR_CLKGATECTL_USE_CLKG_MASK     0x00300000UL
+#define EUR_CR_CLKGATECTL_USE_CLKG_SHIFT    20
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000UL
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATESTATUS                0x0004
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_MASK   0x00000001UL
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_SHIFT  0
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK  0x00000010UL
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK  0x00000100UL
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK   0x00001000UL
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT  12
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK  0x00010000UL
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_MASK  0x00100000UL
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_SHIFT 20
+#define EUR_CR_CLKGATECTLOVR                0x0008
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_MASK   0x00000003UL
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_SHIFT  0
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK  0x00000030UL
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK  0x00000300UL
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK   0x00003000UL
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT  12
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK  0x00030000UL
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_MASK  0x00300000UL
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_SHIFT 20
+#define EUR_CR_CORE_ID                      0x0010
+#define EUR_CR_CORE_ID_CONFIG_MASK          0x0000FFFFUL
+#define EUR_CR_CORE_ID_CONFIG_SHIFT         0
+#define EUR_CR_CORE_ID_ID_MASK              0xFFFF0000UL
+#define EUR_CR_CORE_ID_ID_SHIFT             16
+#define EUR_CR_CORE_REVISION                0x0014
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFUL
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK     0x0000FF00UL
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT    8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK     0x00FF0000UL
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT    16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK  0xFF000000UL
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_DESIGNER_REV_FIELD1          0x0018
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFUL
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2          0x001C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFUL
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_SOFT_RESET                   0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK    0x00000001UL
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT   0
+#define EUR_CR_SOFT_RESET_TWOD_RESET_MASK   0x00000002UL
+#define EUR_CR_SOFT_RESET_TWOD_RESET_SHIFT  1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK    0x00000004UL
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT   2
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK     0x00000008UL
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT    3
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK    0x00000010UL
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT   4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK    0x00000020UL
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT   5
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK    0x00000040UL
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT   6
+#define EUR_CR_EVENT_HOST_ENABLE2           0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_BIF_REQUESTER_FAULT_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_ENABLE2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2            0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_BIF_REQUESTER_FAULT_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_CLEAR2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2                0x0118
+#define EUR_CR_EVENT_STATUS2_BIF_REQUESTER_FAULT_MASK 0x00000010UL
+#define EUR_CR_EVENT_STATUS2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_MASK 0x00000008UL
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_MASK 0x00000004UL
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS                 0x012CUL
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK      0x20000000UL
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT     29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000UL
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000UL
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK   0x00100000UL
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT  20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK   0x00020000UL
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT  17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK   0x00004000UL
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT  14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK  0x00000800UL
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK  0x00000400UL
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE            0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000UL
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000UL
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000UL
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800UL
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400UL
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR             0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK  0x20000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000UL
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000UL
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000UL
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800UL
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400UL
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_PDS                          0x0ABC
+#define EUR_CR_PDS_DOUT_TIMEOUT_DISABLE_MASK 0x00000040UL
+#define EUR_CR_PDS_DOUT_TIMEOUT_DISABLE_SHIFT 6
+#define EUR_CR_PDS_EXEC_BASE                0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK      0xFFF00000UL
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT     20
+#define EUR_CR_EVENT_KICKER                 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK    0xFFFFFFF0UL
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT   4
+#define EUR_CR_EVENT_KICK                   0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK          0x00000001UL
+#define EUR_CR_EVENT_KICK_NOW_SHIFT         0
+#define EUR_CR_EVENT_TIMER                  0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK      0x01000000UL
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT     24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK       0x00FFFFFFUL
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT      0
+#define EUR_CR_PDS_INV0                     0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK            0x00000001UL
+#define EUR_CR_PDS_INV0_DSC_SHIFT           0
+#define EUR_CR_PDS_INV1                     0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK            0x00000001UL
+#define EUR_CR_PDS_INV1_DSC_SHIFT           0
+#define EUR_CR_PDS_INV2                     0x0AD8
+#define EUR_CR_PDS_INV2_DSC_MASK            0x00000001UL
+#define EUR_CR_PDS_INV2_DSC_SHIFT           0
+#define EUR_CR_PDS_INV3                     0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK            0x00000001UL
+#define EUR_CR_PDS_INV3_DSC_SHIFT           0
+#define EUR_CR_PDS_INV_CSC                  0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK        0x00000001UL
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT       0
+#define EUR_CR_PDS_PC_BASE                  0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK     0x3FFFFFFFUL
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT    0
+#define EUR_CR_BIF_CTRL                     0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK      0x00000001UL
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT     0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK          0x00000002UL
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT         1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK          0x00000004UL
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT         2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK        0x00000008UL
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT       3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK    0x00000010UL
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT   4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK  0x00000400UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_MASK 0x00000800UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_SHIFT 11
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK 0x00010000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_SHIFT 16
+#define EUR_CR_BIF_INT_STAT                 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK      0x00003FFFUL
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT     0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK    0x00004000UL
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT   14
+#define EUR_CR_BIF_FAULT                    0x0C08
+#define EUR_CR_BIF_FAULT_ADDR_MASK          0xFFFFF000UL
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT         12
+#define EUR_CR_BIF_TILE0                    0x0C0C
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE0_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE0_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE1                    0x0C10
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE1_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE1_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE2                    0x0C14
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE2_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE2_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE3                    0x0C18
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE3_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE3_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE4                    0x0C1C
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE4_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE4_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE5                    0x0C20
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE5_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE5_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE6                    0x0C24
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE6_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE6_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE7                    0x0C28
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE7_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE7_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE8                    0x0C2C
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE8_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE8_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE9                    0x0C30
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE9_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE9_CFG_SHIFT          24
+#define EUR_CR_BIF_DIR_LIST_BASE1           0x0C38
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE2           0x0C3C
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE3           0x0C40
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE4           0x0C44
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE5           0x0C48
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE6           0x0C4C
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE7           0x0C50
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE8           0x0C54
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE9           0x0C58
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE10          0x0C5C
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE11          0x0C60
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE12          0x0C64
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE13          0x0C68
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE14          0x0C6C
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE15          0x0C70
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_SHIFT 12
+#define EUR_CR_BIF_BANK_SET                 0x0C74
+#define EUR_CR_BIF_BANK_SET_SELECT_MASK     0x000003FFUL
+#define EUR_CR_BIF_BANK_SET_SELECT_SHIFT    0
+#define EUR_CR_BIF_BANK0                    0x0C78
+#define EUR_CR_BIF_BANK0_INDEX_EDM_MASK     0x0000000FUL
+#define EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT    0
+#define EUR_CR_BIF_BANK0_INDEX_TA_MASK      0x000000F0UL
+#define EUR_CR_BIF_BANK0_INDEX_TA_SHIFT     4
+#define EUR_CR_BIF_BANK0_INDEX_HOST_MASK    0x00000F00UL
+#define EUR_CR_BIF_BANK0_INDEX_HOST_SHIFT   8
+#define EUR_CR_BIF_BANK0_INDEX_3D_MASK      0x0000F000UL
+#define EUR_CR_BIF_BANK0_INDEX_3D_SHIFT     12
+#define EUR_CR_BIF_BANK0_INDEX_2D_MASK      0x000F0000UL
+#define EUR_CR_BIF_BANK0_INDEX_2D_SHIFT     16
+#define EUR_CR_BIF_BANK1                    0x0C7C
+#define EUR_CR_BIF_BANK1_INDEX_EDM_MASK     0x0000000FUL
+#define EUR_CR_BIF_BANK1_INDEX_EDM_SHIFT    0
+#define EUR_CR_BIF_BANK1_INDEX_TA_MASK      0x000000F0UL
+#define EUR_CR_BIF_BANK1_INDEX_TA_SHIFT     4
+#define EUR_CR_BIF_BANK1_INDEX_HOST_MASK    0x00000F00UL
+#define EUR_CR_BIF_BANK1_INDEX_HOST_SHIFT   8
+#define EUR_CR_BIF_BANK1_INDEX_3D_MASK      0x0000F000UL
+#define EUR_CR_BIF_BANK1_INDEX_3D_SHIFT     12
+#define EUR_CR_BIF_BANK1_INDEX_2D_MASK      0x000F0000UL
+#define EUR_CR_BIF_BANK1_INDEX_2D_SHIFT     16
+#define EUR_CR_BIF_ADT_TTE                  0x0C80
+#define EUR_CR_BIF_ADT_TTE_VALUE_MASK       0x000000FFUL
+#define EUR_CR_BIF_ADT_TTE_VALUE_SHIFT      0
+#define EUR_CR_BIF_DIR_LIST_BASE0           0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_TWOD_REQ_BASE            0x0C88
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK  0xFFF00000UL
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_TA_REQ_BASE              0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK    0xFFF00000UL
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1      0x0C94
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_MMU_MASK 0x00000007UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_MMU_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_CACHE_MASK 0x00000038UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_CACHE_SHIFT 3
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_VDM_MASK 0x000001C0UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_VDM_SHIFT 6
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TE_MASK 0x00000E00UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TE_SHIFT 9
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TWOD_MASK 0x00007000UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TWOD_SHIFT 12
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_PBE_MASK 0x00038000UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_PBE_SHIFT 15
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2      0x0C98
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_HOST_MASK 0x00000007UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_HOST_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_USE_MASK 0x00000038UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_USE_SHIFT 3
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_ISP_MASK 0x000001C0UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_ISP_SHIFT 6
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_TSPP_MASK 0x00000E00UL
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_TSPP_SHIFT 9
+#define EUR_CR_BIF_MEM_ARB_CONFIG           0x0CA0
+#define EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_MASK 0x0000000FUL
+#define EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_MASK 0x00000FF0UL
+#define EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_SHIFT 4
+#define EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_MASK 0x00FFF000UL
+#define EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_SHIFT 12
+#define EUR_CR_BIF_MEM_REQ_STAT             0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK  0x000000FFUL
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_3D_REQ_BASE              0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK    0xFFF00000UL
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_ZLS_REQ_BASE             0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK   0xFFF00000UL
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT  20
+#define EUR_CR_BIF_BANK_STATUS              0x0CB4
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_MASK 0x00000001UL
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SHIFT 0
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_MASK 0x00000002UL
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SHIFT 1
+#define EUR_CR_2D_BLIT_STATUS               0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFUL
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK     0x01000000UL
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT    24
+#define EUR_CR_2D_VIRTUAL_FIFO_0            0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001UL
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EUL
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0UL
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000UL
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1            0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFUL
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000UL
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000UL
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+#define EUR_CR_2D_SOCIF                     0x0E18
+#define EUR_CR_2D_SOCIF_FREESPACE_MASK      0x000000FFUL
+#define EUR_CR_2D_SOCIF_FREESPACE_SHIFT     0
+#define EUR_CR_2D_ALPHA						0x0E1C
+#define EUR_CR_2D_ALPHA_COMPONENT_ONE_MASK  0x0000FF00UL
+#define EUR_CR_2D_ALPHA_COMPONENT_ONE_SHIFT 8
+#define EUR_CR_2D_ALPHA_COMPONENT_ZERO_MASK 0x000000FFUL
+#define EUR_CR_2D_ALPHA_COMPONENT_ZERO_SHIFT 0
+#define EUR_CR_USE_CODE_BASE(X)     (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK      0x01FFFFFFUL
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT     0
+#define EUR_CR_USE_CODE_BASE_DM_MASK        0x06000000UL
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT       25
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#define EUR_CR_MNE_CR_CTRL						0x0D00
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_MASK			0x00008000UL
+#define EUR_CR_MNE_CR_CTRL_INVAL				0x0D20
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx540defs.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx540defs.h
new file mode 100755
index 0000000..92a19f9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx540defs.h
@@ -0,0 +1,586 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _SGX540DEFS_KM_H_
+#define _SGX540DEFS_KM_H_
+
+#define EUR_CR_CLKGATECTL                   0x0000
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK     0x00000003UL
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT    0
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_MASK    0x0000000CUL
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SHIFT   2
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK     0x00000030UL
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT    4
+#define EUR_CR_CLKGATECTL_TE_CLKG_MASK      0x000000C0UL
+#define EUR_CR_CLKGATECTL_TE_CLKG_SHIFT     6
+#define EUR_CR_CLKGATECTL_MTE_CLKG_MASK     0x00000300UL
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SHIFT    8
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK     0x00000C00UL
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT    10
+#define EUR_CR_CLKGATECTL_VDM_CLKG_MASK     0x00003000UL
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SHIFT    12
+#define EUR_CR_CLKGATECTL_PDS_CLKG_MASK     0x0000C000UL
+#define EUR_CR_CLKGATECTL_PDS_CLKG_SHIFT    14
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_MASK 0x00030000UL
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK      0x000C0000UL
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT     18
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000UL
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_MASK  0x10000000UL
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SHIFT 28
+#define EUR_CR_CLKGATECTL2                  0x0004
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK    0x00000003UL
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT   0
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_MASK 0x0000000CUL
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_MASK 0x00000030UL
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_MASK   0x000000C0UL
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SHIFT  6
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_MASK   0x00000300UL
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SHIFT  8
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_MASK   0x00000C00UL
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SHIFT  10
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_MASK  0x00003000UL
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_MASK   0x0000C000UL
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SHIFT  14
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_MASK   0x00030000UL
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SHIFT  16
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_MASK   0x000C0000UL
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SHIFT  18
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_MASK  0x00300000UL
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_SHIFT 20
+#define EUR_CR_CLKGATESTATUS                0x0008
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK  0x00000001UL
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_MASK 0x00000002UL
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SHIFT 1
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK  0x00000004UL
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 2
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_MASK   0x00000008UL
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SHIFT  3
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_MASK  0x00000010UL
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK  0x00000020UL
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 5
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_MASK  0x00000040UL
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SHIFT 6
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_MASK  0x00000080UL
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_SHIFT 7
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_MASK  0x00000100UL
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_MASK 0x00000200UL
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_SHIFT 9
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_MASK 0x00000400UL
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SHIFT 10
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_MASK 0x00000800UL
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SHIFT 11
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_MASK 0x00001000UL
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_MASK 0x00002000UL
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SHIFT 13
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_MASK 0x00004000UL
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_SHIFT 14
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_MASK 0x00008000UL
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SHIFT 15
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_MASK 0x00010000UL
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_MASK 0x00020000UL
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SHIFT 17
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_MASK 0x00040000UL
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_SHIFT 18
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_MASK 0x00080000UL
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_SHIFT 19
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK   0x00100000UL
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT  20
+#define EUR_CR_CLKGATECTLOVR                0x000C
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK  0x00000003UL
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_MASK 0x0000000CUL
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SHIFT 2
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK  0x00000030UL
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_MASK   0x000000C0UL
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SHIFT  6
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_MASK  0x00000300UL
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK  0x00000C00UL
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 10
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_MASK  0x00003000UL
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_MASK  0x0000C000UL
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_SHIFT 14
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_MASK 0x00030000UL
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK   0x000C0000UL
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT  18
+#define EUR_CR_POWER                        0x001C
+#define EUR_CR_POWER_PIPE_DISABLE_MASK      0x00000001UL
+#define EUR_CR_POWER_PIPE_DISABLE_SHIFT     0
+#define EUR_CR_CORE_ID                      0x0020
+#define EUR_CR_CORE_ID_CONFIG_MASK          0x0000FFFFUL
+#define EUR_CR_CORE_ID_CONFIG_SHIFT         0
+#define EUR_CR_CORE_ID_ID_MASK              0xFFFF0000UL
+#define EUR_CR_CORE_ID_ID_SHIFT             16
+#define EUR_CR_CORE_REVISION                0x0024
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFUL
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK     0x0000FF00UL
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT    8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK     0x00FF0000UL
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT    16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK  0xFF000000UL
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_DESIGNER_REV_FIELD1          0x0028
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFUL
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2          0x002C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFUL
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_SOFT_RESET                   0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK    0x00000001UL
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT   0
+#define EUR_CR_SOFT_RESET_VDM_RESET_MASK    0x00000002UL
+#define EUR_CR_SOFT_RESET_VDM_RESET_SHIFT   1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK    0x00000004UL
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT   2
+#define EUR_CR_SOFT_RESET_TE_RESET_MASK     0x00000008UL
+#define EUR_CR_SOFT_RESET_TE_RESET_SHIFT    3
+#define EUR_CR_SOFT_RESET_MTE_RESET_MASK    0x00000010UL
+#define EUR_CR_SOFT_RESET_MTE_RESET_SHIFT   4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK    0x00000020UL
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT   5
+#define EUR_CR_SOFT_RESET_ISP2_RESET_MASK   0x00000040UL
+#define EUR_CR_SOFT_RESET_ISP2_RESET_SHIFT  6
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK    0x00000080UL
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT   7
+#define EUR_CR_SOFT_RESET_PDS_RESET_MASK    0x00000100UL
+#define EUR_CR_SOFT_RESET_PDS_RESET_SHIFT   8
+#define EUR_CR_SOFT_RESET_PBE_RESET_MASK    0x00000200UL
+#define EUR_CR_SOFT_RESET_PBE_RESET_SHIFT   9
+#define EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK 0x00000400UL
+#define EUR_CR_SOFT_RESET_CACHEL2_RESET_SHIFT 10
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK 0x00000800UL
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_SHIFT 11
+#define EUR_CR_SOFT_RESET_MADD_RESET_MASK   0x00001000UL
+#define EUR_CR_SOFT_RESET_MADD_RESET_SHIFT  12
+#define EUR_CR_SOFT_RESET_ITR_RESET_MASK    0x00002000UL
+#define EUR_CR_SOFT_RESET_ITR_RESET_SHIFT   13
+#define EUR_CR_SOFT_RESET_TEX_RESET_MASK    0x00004000UL
+#define EUR_CR_SOFT_RESET_TEX_RESET_SHIFT   14
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK    0x00008000UL
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT   15
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK 0x00010000UL
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_SHIFT 16
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK     0x00020000UL
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT    17
+#define EUR_CR_EVENT_HOST_ENABLE2           0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2            0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2                0x0118
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK   0x00000010UL
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT  4
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK   0x00000008UL
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT  3
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK   0x00000004UL
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT  2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS                 0x012CUL
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK      0x20000000UL
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT     29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000UL
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000UL
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK   0x00100000UL
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT  20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK   0x00020000UL
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT  17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK   0x00004000UL
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT  14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK  0x00000800UL
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK  0x00000400UL
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE            0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000UL
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000UL
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000UL
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800UL
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400UL
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR             0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK  0x20000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000UL
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000UL
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000UL
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800UL
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400UL
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_TIMER                        0x0144
+#define EUR_CR_TIMER_VALUE_MASK             0xFFFFFFFFUL
+#define EUR_CR_TIMER_VALUE_SHIFT            0
+#define EUR_CR_EVENT_KICK1                  0x0AB0
+#define EUR_CR_EVENT_KICK1_NOW_MASK         0x000000FFUL
+#define EUR_CR_EVENT_KICK1_NOW_SHIFT        0
+#define EUR_CR_PDS_EXEC_BASE                0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK      0x0FF00000UL
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT     20
+#define EUR_CR_EVENT_KICK2                  0x0AC0
+#define EUR_CR_EVENT_KICK2_NOW_MASK         0x00000001UL
+#define EUR_CR_EVENT_KICK2_NOW_SHIFT        0
+#define EUR_CR_EVENT_KICKER                 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK    0x0FFFFFF0UL
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT   4
+#define EUR_CR_EVENT_KICK                   0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK          0x00000001UL
+#define EUR_CR_EVENT_KICK_NOW_SHIFT         0
+#define EUR_CR_EVENT_TIMER                  0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK      0x01000000UL
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT     24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK       0x00FFFFFFUL
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT      0
+#define EUR_CR_PDS_INV0                     0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK            0x00000001UL
+#define EUR_CR_PDS_INV0_DSC_SHIFT           0
+#define EUR_CR_PDS_INV1                     0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK            0x00000001UL
+#define EUR_CR_PDS_INV1_DSC_SHIFT           0
+#define EUR_CR_EVENT_KICK3                  0x0AD8
+#define EUR_CR_EVENT_KICK3_NOW_MASK         0x00000001UL
+#define EUR_CR_EVENT_KICK3_NOW_SHIFT        0
+#define EUR_CR_PDS_INV3                     0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK            0x00000001UL
+#define EUR_CR_PDS_INV3_DSC_SHIFT           0
+#define EUR_CR_PDS_INV_CSC                  0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK        0x00000001UL
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT       0
+#define EUR_CR_PDS_PC_BASE                  0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK     0x00FFFFFFUL
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT    0
+#define EUR_CR_BIF_CTRL                     0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK      0x00000001UL
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT     0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK          0x00000002UL
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT         1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK          0x00000004UL
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT         2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK        0x00000008UL
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT       3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK    0x00000010UL
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT   4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK  0x00000400UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+#define EUR_CR_BIF_INT_STAT                 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK      0x00003FFFUL
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT     0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK    0x00004000UL
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT   14
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000UL
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+#define EUR_CR_BIF_FAULT                    0x0C08
+#define EUR_CR_BIF_FAULT_SB_MASK            0x000001F0UL
+#define EUR_CR_BIF_FAULT_SB_SHIFT           4
+#define EUR_CR_BIF_FAULT_ADDR_MASK          0x0FFFF000UL
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT         12
+#define EUR_CR_BIF_DIR_LIST_BASE0           0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_TA_REQ_BASE              0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK    0x0FF00000UL
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_MEM_REQ_STAT             0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK  0x000000FFUL
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_3D_REQ_BASE              0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK    0x0FF00000UL
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_ZLS_REQ_BASE             0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK   0x0FF00000UL
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT  20
+#define EUR_CR_2D_BLIT_STATUS               0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFUL
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK     0x01000000UL
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT    24
+#define EUR_CR_2D_VIRTUAL_FIFO_0            0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001UL
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EUL
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0UL
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000UL
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1            0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFUL
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000UL
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000UL
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+#define EUR_CR_USE_CODE_BASE(X)     (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK      0x00FFFFFFUL
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT     0
+#define EUR_CR_USE_CODE_BASE_DM_MASK        0x03000000UL
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT       24
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+#define EUR_CR_MNE_CR_CTRL						0x0D00
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_N_MASK		0x00010000UL
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_N_SHIFT		16
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_MASK			0x00008000UL
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_SHIFT			15
+#define EUR_CR_MNE_CR_CTRL_USE_INVAL_ADDR_MASK	0x00007800UL
+#define EUR_CR_MNE_CR_CTRL_USE_INVAL_ADDR_SHIFT	11
+#define EUR_CR_MNE_CR_CTRL_BYPASS_ALL_MASK		0x00000400UL
+#define EUR_CR_MNE_CR_CTRL_BYPASS_ALL_SHIFT		10
+#define EUR_CR_MNE_CR_CTRL_BYPASS_MASK			0x000003E0UL
+#define EUR_CR_MNE_CR_CTRL_BYPASS_SHIFT			5
+#define EUR_CR_MNE_CR_CTRL_PAUSE_MASK			0x00000010UL
+#define EUR_CR_MNE_CR_CTRL_PAUSE_SHIFT			4
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_MASK		0x0000000EUL
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT		1
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_PDS_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT+2)
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_USEC_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT+1)
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_CACHE_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT)
+#define EUR_CR_MNE_CR_CTRL_INVAL_ALL_MASK		0x00000001UL
+#define EUR_CR_MNE_CR_CTRL_INVAL_ALL_SHIFT		0
+#define EUR_CR_MNE_CR_USE_INVAL					0x0D04
+#define EUR_CR_MNE_CR_USE_INVAL_ADDR_MASK		0xFFFFFFFFUL
+#define EUR_CR_MNE_CR_USE_INVAL_ADDR_SHIFT		0
+#define EUR_CR_MNE_CR_STAT					0x0D08
+#define EUR_CR_MNE_CR_STAT_PAUSED_MASK		0x00000400UL
+#define EUR_CR_MNE_CR_STAT_PAUSED_SHIFT		10
+#define EUR_CR_MNE_CR_STAT_READS_MASK		0x000003FFUL
+#define EUR_CR_MNE_CR_STAT_READS_SHIFT		0
+#define EUR_CR_MNE_CR_STAT_STATS			0x0D0C
+#define EUR_CR_MNE_CR_STAT_STATS_RST_MASK	0x000FFFF0UL
+#define EUR_CR_MNE_CR_STAT_STATS_RST_SHIFT	4
+#define EUR_CR_MNE_CR_STAT_STATS_SEL_MASK	0x0000000FUL
+#define EUR_CR_MNE_CR_STAT_STATS_SEL_SHIFT	0
+#define EUR_CR_MNE_CR_STAT_STATS_OUT				0x0D10
+#define EUR_CR_MNE_CR_STAT_STATS_OUT_VALUE_MASK		0xFFFFFFFFUL
+#define EUR_CR_MNE_CR_STAT_STATS_OUT_VALUE_SHIFT	0
+#define EUR_CR_MNE_CR_EVENT_STATUS				0x0D14
+#define EUR_CR_MNE_CR_EVENT_STATUS_INVAL_MASK	0x00000001UL
+#define EUR_CR_MNE_CR_EVENT_STATUS_INVAL_SHIFT	0
+#define EUR_CR_MNE_CR_EVENT_CLEAR				0x0D18
+#define EUR_CR_MNE_CR_EVENT_CLEAR_INVAL_MASK	0x00000001UL
+#define EUR_CR_MNE_CR_EVENT_CLEAR_INVAL_SHIFT	0
+#define EUR_CR_MNE_CR_CTRL_INVAL				0x0D20
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx545defs.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx545defs.h
new file mode 100755
index 0000000..cad51f5
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgx545defs.h
@@ -0,0 +1,828 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _SGX545DEFS_KM_H_
+#define _SGX545DEFS_KM_H_
+
+#define EUR_CR_CLKGATECTL                   0x0000
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK     0x00000003UL
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT    0
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_MASK    0x0000000CUL
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SHIFT   2
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK     0x00000030UL
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT    4
+#define EUR_CR_CLKGATECTL_TE_CLKG_MASK      0x000000C0UL
+#define EUR_CR_CLKGATECTL_TE_CLKG_SHIFT     6
+#define EUR_CR_CLKGATECTL_MTE_CLKG_MASK     0x00000300UL
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SHIFT    8
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK     0x00000C00UL
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT    10
+#define EUR_CR_CLKGATECTL_VDM_CLKG_MASK     0x00003000UL
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SHIFT    12
+#define EUR_CR_CLKGATECTL_PDS0_CLKG_MASK    0x0000C000UL
+#define EUR_CR_CLKGATECTL_PDS0_CLKG_SHIFT   14
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000UL
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATECTL2                  0x0004
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK    0x00000003UL
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT   0
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_MASK 0x0000000CUL
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_MASK 0x00000030UL
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_MASK   0x000000C0UL
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SHIFT  6
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_MASK   0x00000300UL
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SHIFT  8
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_MASK   0x00000C00UL
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SHIFT  10
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_MASK  0x00003000UL
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_MASK   0x0000C000UL
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SHIFT  14
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_MASK   0x00030000UL
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SHIFT  16
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_MASK   0x000C0000UL
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SHIFT  18
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_MASK  0x00300000UL
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_SHIFT 20
+#define EUR_CR_CLKGATECTL2_PDS1_CLKG_MASK   0x00C00000UL
+#define EUR_CR_CLKGATECTL2_PDS1_CLKG_SHIFT  22
+#define EUR_CR_CLKGATESTATUS                0x0008
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK  0x00000001UL
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_MASK 0x00000002UL
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SHIFT 1
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK  0x00000004UL
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 2
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_MASK   0x00000008UL
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SHIFT  3
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_MASK  0x00000010UL
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK  0x00000020UL
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 5
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_MASK  0x00000040UL
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SHIFT 6
+#define EUR_CR_CLKGATESTATUS_PDS0_CLKS_MASK 0x00000080UL
+#define EUR_CR_CLKGATESTATUS_PDS0_CLKS_SHIFT 7
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_MASK  0x00000100UL
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_MASK 0x00000200UL
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_SHIFT 9
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_MASK 0x00000400UL
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SHIFT 10
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_MASK 0x00000800UL
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SHIFT 11
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_MASK 0x00001000UL
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_MASK 0x00002000UL
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SHIFT 13
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_MASK 0x00004000UL
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_SHIFT 14
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_MASK 0x00008000UL
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SHIFT 15
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_MASK 0x00010000UL
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_MASK 0x00020000UL
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SHIFT 17
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_MASK 0x00040000UL
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_SHIFT 18
+#define EUR_CR_CLKGATESTATUS_PDS1_CLKS_MASK 0x00080000UL
+#define EUR_CR_CLKGATESTATUS_PDS1_CLKS_SHIFT 19
+#define EUR_CR_CLKGATECTLOVR                0x000C
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK  0x00000003UL
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_MASK 0x0000000CUL
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SHIFT 2
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK  0x00000030UL
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_MASK   0x000000C0UL
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SHIFT  6
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_MASK  0x00000300UL
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK  0x00000C00UL
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 10
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_MASK  0x00003000UL
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_PDS0_CLKO_MASK 0x0000C000UL
+#define EUR_CR_CLKGATECTLOVR_PDS0_CLKO_SHIFT 14
+#define EUR_CR_CORE_ID                      0x001C
+#define EUR_CR_CORE_ID_CONFIG_MASK          0x0000FFFFUL
+#define EUR_CR_CORE_ID_CONFIG_SHIFT         0
+#define EUR_CR_CORE_ID_ID_MASK              0xFFFF0000UL
+#define EUR_CR_CORE_ID_ID_SHIFT             16
+#define EUR_CR_CORE_REVISION                0x0020
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFUL
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK     0x0000FF00UL
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT    8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK     0x00FF0000UL
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT    16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK  0xFF000000UL
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_DESIGNER_REV_FIELD1          0x0024
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFUL
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2          0x002C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFUL
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_SOFT_RESET                   0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK    0x00000001UL
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT   0
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK    0x00000002UL
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT   1
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK     0x00000004UL
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT    2
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK    0x00000008UL
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT   3
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK    0x00000010UL
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT   4
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK    0x00000020UL
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT   5
+#define EUR_CR_EVENT_HOST_ENABLE2           0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_VDM_CONTEXT_LOAD_MASK 0x00004000UL
+#define EUR_CR_EVENT_HOST_ENABLE2_VDM_CONTEXT_LOAD_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE2_VDM_TASK_KICKED_MASK 0x00002000UL
+#define EUR_CR_EVENT_HOST_ENABLE2_VDM_TASK_KICKED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE2_OTPM_MEM_CLEARED_MASK 0x00001000UL
+#define EUR_CR_EVENT_HOST_ENABLE2_OTPM_MEM_CLEARED_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE2_OTPM_FLUSHED_INV_MASK 0x00000800UL
+#define EUR_CR_EVENT_HOST_ENABLE2_OTPM_FLUSHED_INV_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE2_DCU_INVALCOMPLETE_MASK 0x00000400UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DCU_INVALCOMPLETE_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE2_GSG_FLUSHED_MASK 0x00000200UL
+#define EUR_CR_EVENT_HOST_ENABLE2_GSG_FLUSHED_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE2_GSG_LOADED_MASK 0x00000100UL
+#define EUR_CR_EVENT_HOST_ENABLE2_GSG_LOADED_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000080UL
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000040UL
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000020UL
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2            0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_VDM_CONTEXT_LOAD_MASK 0x00004000UL
+#define EUR_CR_EVENT_HOST_CLEAR2_VDM_CONTEXT_LOAD_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR2_VDM_TASK_KICKED_MASK 0x00002000UL
+#define EUR_CR_EVENT_HOST_CLEAR2_VDM_TASK_KICKED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR2_OTPM_MEM_CLEARED_MASK 0x00001000UL
+#define EUR_CR_EVENT_HOST_CLEAR2_OTPM_MEM_CLEARED_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR2_OTPM_FLUSHED_INV_MASK 0x00000800UL
+#define EUR_CR_EVENT_HOST_CLEAR2_OTPM_FLUSHED_INV_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR2_DCU_INVALCOMPLETE_MASK 0x00000400UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DCU_INVALCOMPLETE_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR2_GSG_FLUSHED_MASK 0x00000200UL
+#define EUR_CR_EVENT_HOST_CLEAR2_GSG_FLUSHED_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR2_GSG_LOADED_MASK 0x00000100UL
+#define EUR_CR_EVENT_HOST_CLEAR2_GSG_LOADED_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000080UL
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000040UL
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000020UL
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2                0x0118
+#define EUR_CR_EVENT_STATUS2_VDM_CONTEXT_LOAD_MASK 0x00004000UL
+#define EUR_CR_EVENT_STATUS2_VDM_CONTEXT_LOAD_SHIFT 14
+#define EUR_CR_EVENT_STATUS2_VDM_TASK_KICKED_MASK 0x00002000UL
+#define EUR_CR_EVENT_STATUS2_VDM_TASK_KICKED_SHIFT 13
+#define EUR_CR_EVENT_STATUS2_OTPM_MEM_CLEARED_MASK 0x00001000UL
+#define EUR_CR_EVENT_STATUS2_OTPM_MEM_CLEARED_SHIFT 12
+#define EUR_CR_EVENT_STATUS2_OTPM_FLUSHED_INV_MASK 0x00000800UL
+#define EUR_CR_EVENT_STATUS2_OTPM_FLUSHED_INV_SHIFT 11
+#define EUR_CR_EVENT_STATUS2_DCU_INVALCOMPLETE_MASK 0x00000400UL
+#define EUR_CR_EVENT_STATUS2_DCU_INVALCOMPLETE_SHIFT 10
+#define EUR_CR_EVENT_STATUS2_GSG_FLUSHED_MASK 0x00000200UL
+#define EUR_CR_EVENT_STATUS2_GSG_FLUSHED_SHIFT 9
+#define EUR_CR_EVENT_STATUS2_GSG_LOADED_MASK 0x00000100UL
+#define EUR_CR_EVENT_STATUS2_GSG_LOADED_SHIFT 8
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK   0x00000080UL
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT  7
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK   0x00000040UL
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT  6
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK   0x00000020UL
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT  5
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_MASK 0x00000008UL
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_MASK 0x00000004UL
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002UL
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001UL
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS                 0x012CUL
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK      0x20000000UL
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT     29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_ISP2_ZLS_CSW_FINISHED_MASK 0x00200000UL
+#define EUR_CR_EVENT_STATUS_ISP2_ZLS_CSW_FINISHED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK   0x00100000UL
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT  20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK   0x00004000UL
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT  14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK  0x00000800UL
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK  0x00000400UL
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE            0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_ISP2_ZLS_CSW_FINISHED_MASK 0x00200000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP2_ZLS_CSW_FINISHED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000UL
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000UL
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800UL
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400UL
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR             0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK  0x20000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_ISP2_ZLS_CSW_FINISHED_MASK 0x00200000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP2_ZLS_CSW_FINISHED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000UL
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000UL
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000UL
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000UL
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000UL
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000UL
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000UL
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800UL
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400UL
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001UL
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_PDS_EXEC_BASE                0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK      0xFFF00000UL
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT     20
+#define EUR_CR_EVENT_KICKER                 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK    0xFFFFFFF0UL
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT   4
+#define EUR_CR_EVENT_KICK                   0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK          0x00000001UL
+#define EUR_CR_EVENT_KICK_NOW_SHIFT         0
+#define EUR_CR_EVENT_TIMER                  0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK      0x01000000UL
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT     24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK       0x00FFFFFFUL
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT      0
+#define EUR_CR_PDS_INV0                     0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK            0x00000001UL
+#define EUR_CR_PDS_INV0_DSC_SHIFT           0
+#define EUR_CR_PDS_INV1                     0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK            0x00000001UL
+#define EUR_CR_PDS_INV1_DSC_SHIFT           0
+#define EUR_CR_PDS_INV3                     0x0AD8
+#define EUR_CR_PDS_INV3_DSC_MASK            0x00000001UL
+#define EUR_CR_PDS_INV3_DSC_SHIFT           0
+#define EUR_CR_PDS_INV_CSC                  0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK        0x00000001UL
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT       0
+#define EUR_CR_EVENT_KICK1                  0x0AE4
+#define EUR_CR_EVENT_KICK1_NOW_MASK         0x000000FFUL
+#define EUR_CR_EVENT_KICK1_NOW_SHIFT        0
+#define EUR_CR_EVENT_KICK2                  0x0AE8
+#define EUR_CR_EVENT_KICK2_NOW_MASK         0x00000001UL
+#define EUR_CR_EVENT_KICK2_NOW_SHIFT        0
+#define EUR_CR_EVENT_KICK3                  0x0AEC
+#define EUR_CR_EVENT_KICK3_NOW_MASK         0x00000001UL
+#define EUR_CR_EVENT_KICK3_NOW_SHIFT        0
+#define EUR_CR_BIF_CTRL                     0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK      0x00000001UL
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT     0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK          0x00000002UL
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT         1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK          0x00000004UL
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT         2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK        0x00000008UL
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT       3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK    0x00000010UL
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT   4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK  0x00000400UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00000800UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 11
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00001000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00002000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00004000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK 0x00008000UL
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_SHIFT 15
+#define EUR_CR_BIF_INT_STAT                 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK  0x0000FFFFUL
+#define EUR_CR_BIF_INT_STAT_FAULT_REQ_SHIFT 0
+#define EUR_CR_BIF_INT_STAT_FAULT_TYPE_MASK 0x00070000UL
+#define EUR_CR_BIF_INT_STAT_FAULT_TYPE_SHIFT 16
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00080000UL
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 19
+#define EUR_CR_BIF_FAULT                    0x0C08
+#define EUR_CR_BIF_FAULT_CID_MASK           0x0000000FUL
+#define EUR_CR_BIF_FAULT_CID_SHIFT          0
+#define EUR_CR_BIF_FAULT_SB_MASK            0x000001F0UL
+#define EUR_CR_BIF_FAULT_SB_SHIFT           4
+#define EUR_CR_BIF_FAULT_ADDR_MASK          0xFFFFF000UL
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT         12
+
+#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS)
+#define EUR_CR_BIF_TILE0                    0x0C0C
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE0_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE0_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE1                    0x0C10
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE1_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE1_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE2                    0x0C14
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE2_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE2_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE3                    0x0C18
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE3_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE3_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE4                    0x0C1C
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE4_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE4_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE5                    0x0C20
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE5_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE5_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE6                    0x0C24
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE6_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE6_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE7                    0x0C28
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE7_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE7_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE8                    0x0C2C
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE8_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE8_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE9                    0x0C30
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE9_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE9_CFG_SHIFT          24
+
+#else
+
+#define EUR_CR_BIF_TILE0                    0x0C0C
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE0_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE0_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE1                    0x0C10
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE1_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE1_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE2                    0x0C14
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE2_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE2_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE3                    0x0C18
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE3_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE3_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE4                    0x0C1C
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE4_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE4_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE5                    0x0C20
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE5_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE5_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE6                    0x0C24
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE6_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE6_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE7                    0x0C28
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE7_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE7_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE8                    0x0C2C
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE8_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE8_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE9                    0x0C30
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_MASK   0x00000FFFUL
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_MASK   0x00FFF000UL
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE9_CFG_MASK           0x0F000000UL
+#define EUR_CR_BIF_TILE9_CFG_SHIFT          24
+#endif
+
+#define EUR_CR_BIF_DIR_LIST_BASE1           0x0C38
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE2           0x0C3C
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE3           0x0C40
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE4           0x0C44
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE5           0x0C48
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE6           0x0C4C
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE7           0x0C50
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE8           0x0C54
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE9           0x0C58
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE10          0x0C5C
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE11          0x0C60
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE12          0x0C64
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE13          0x0C68
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE14          0x0C6C
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE15          0x0C70
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_SHIFT 12
+#define EUR_CR_BIF_BANK_SET                 0x0C74
+#define EUR_CR_BIF_BANK_SET_SELECT_2D_MASK  0x00000001UL
+#define EUR_CR_BIF_BANK_SET_SELECT_2D_SHIFT 0
+#define EUR_CR_BIF_BANK_SET_SELECT_3D_MASK  0x0000000CUL
+#define EUR_CR_BIF_BANK_SET_SELECT_3D_SHIFT 2
+#define EUR_CR_BIF_BANK_SET_SELECT_HOST_MASK 0x00000010UL
+#define EUR_CR_BIF_BANK_SET_SELECT_HOST_SHIFT 4
+#define EUR_CR_BIF_BANK_SET_SELECT_TA_MASK  0x000000C0UL
+#define EUR_CR_BIF_BANK_SET_SELECT_TA_SHIFT 6
+#define EUR_CR_BIF_BANK_SET_SELECT_EDM_MASK 0x00000100UL
+#define EUR_CR_BIF_BANK_SET_SELECT_EDM_SHIFT 8
+#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_MASK 0x00000200UL
+#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_SHIFT 9
+#define EUR_CR_BIF_BANK0                    0x0C78
+#define EUR_CR_BIF_BANK0_INDEX_EDM_MASK     0x0000000FUL
+#define EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT    0
+#define EUR_CR_BIF_BANK0_INDEX_TA_MASK      0x000000F0UL
+#define EUR_CR_BIF_BANK0_INDEX_TA_SHIFT     4
+#define EUR_CR_BIF_BANK0_INDEX_HOST_MASK    0x00000F00UL
+#define EUR_CR_BIF_BANK0_INDEX_HOST_SHIFT   8
+#define EUR_CR_BIF_BANK0_INDEX_3D_MASK      0x0000F000UL
+#define EUR_CR_BIF_BANK0_INDEX_3D_SHIFT     12
+#define EUR_CR_BIF_BANK0_INDEX_2D_MASK      0x000F0000UL
+#define EUR_CR_BIF_BANK0_INDEX_2D_SHIFT     16
+#define EUR_CR_BIF_BANK1                    0x0C7C
+#define EUR_CR_BIF_BANK1_INDEX_EDM_MASK     0x0000000FUL
+#define EUR_CR_BIF_BANK1_INDEX_EDM_SHIFT    0
+#define EUR_CR_BIF_BANK1_INDEX_TA_MASK      0x000000F0UL
+#define EUR_CR_BIF_BANK1_INDEX_TA_SHIFT     4
+#define EUR_CR_BIF_BANK1_INDEX_HOST_MASK    0x00000F00UL
+#define EUR_CR_BIF_BANK1_INDEX_HOST_SHIFT   8
+#define EUR_CR_BIF_BANK1_INDEX_3D_MASK      0x0000F000UL
+#define EUR_CR_BIF_BANK1_INDEX_3D_SHIFT     12
+#define EUR_CR_BIF_BANK1_INDEX_2D_MASK      0x000F0000UL
+#define EUR_CR_BIF_BANK1_INDEX_2D_SHIFT     16
+#define EUR_CR_BIF_DIR_LIST_BASE0           0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000UL
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_TA_REQ_BASE              0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK    0xFFF00000UL
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_MEM_REQ_STAT             0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK  0x000000FFUL
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_3D_REQ_BASE              0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK    0xFFF00000UL
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_ZLS_REQ_BASE             0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK   0xFFF00000UL
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT  20
+#define EUR_CR_BIF_BANK_STATUS              0x0CB4
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_MASK 0x00000001UL
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SHIFT 0
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_MASK 0x00000002UL
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SHIFT 1
+
+#define EUR_CR_BIF_36BIT_ADDRESSING         0x0CCC
+#define EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK 0x00000001UL
+#define EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_SHIFT 0
+
+#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS)
+#define EUR_CR_BIF_TILE0_MIN                0x0CD0
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT  0
+
+#define EUR_CR_BIF_TILE1_MIN                0x0CD4
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SHIFT  0
+
+#define EUR_CR_BIF_TILE2_MIN                0x0CD8
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SHIFT  0
+
+#define EUR_CR_BIF_TILE3_MIN                0x0CDC
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SHIFT  0
+
+#define EUR_CR_BIF_TILE4_MIN                0x0CE0
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SHIFT  0
+
+#define EUR_CR_BIF_TILE5_MIN                0x0CE4
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SHIFT  0
+
+#define EUR_CR_BIF_TILE6_MIN                0x0CE8
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SHIFT  0
+
+#define EUR_CR_BIF_TILE7_MIN                0x0CEC
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SHIFT  0
+
+#define EUR_CR_BIF_TILE8_MIN                0x0CF0
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SHIFT  0
+
+#define EUR_CR_BIF_TILE9_MIN                0x0CF4
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_MASK   0x000FFFFFUL
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SHIFT  0
+#endif
+
+#define EUR_CR_USE_CODE_BASE(X)     (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK      0x01FFFFFFUL
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT     0
+#define EUR_CR_USE_CODE_BASE_DM_MASK        0x06000000UL
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT       25
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+#define EUR_CR_MNE_CR_CTRL						0x0D00
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_N_MASK		0x00010000UL
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_N_SHIFT		16
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_MASK			0x00008000UL
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_SHIFT			15
+#define EUR_CR_MNE_CR_CTRL_USE_INVAL_ADDR_MASK	0x00007800UL
+#define EUR_CR_MNE_CR_CTRL_USE_INVAL_ADDR_SHIFT	11
+#define EUR_CR_MNE_CR_CTRL_BYPASS_ALL_MASK		0x00000400UL
+#define EUR_CR_MNE_CR_CTRL_BYPASS_ALL_SHIFT		10
+#define EUR_CR_MNE_CR_CTRL_BYPASS_MASK			0x000003E0UL
+#define EUR_CR_MNE_CR_CTRL_BYPASS_SHIFT			5
+#define EUR_CR_MNE_CR_CTRL_PAUSE_MASK			0x00000010UL
+#define EUR_CR_MNE_CR_CTRL_PAUSE_SHIFT			4
+
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_MASK		0x0000000EUL
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT		1
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_PDS_MASK 	(1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT+2)
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_USEC_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT+1)
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_CACHE_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT)
+#define EUR_CR_MNE_CR_CTRL_INVAL_ALL_MASK		0x00000001UL
+#define EUR_CR_MNE_CR_CTRL_INVAL_ALL_SHIFT		0
+#define EUR_CR_MNE_CR_USE_INVAL					0x0D04
+#define EUR_CR_MNE_CR_USE_INVAL_ADDR_MASK		0xFFFFFFFFUL
+#define EUR_CR_MNE_CR_USE_INVAL_ADDR_SHIFT		0
+#define EUR_CR_MNE_CR_STAT					0x0D08
+#define EUR_CR_MNE_CR_STAT_PAUSED_MASK		0x00000400UL
+#define EUR_CR_MNE_CR_STAT_PAUSED_SHIFT		10
+#define EUR_CR_MNE_CR_STAT_READS_MASK		0x000003FFUL
+#define EUR_CR_MNE_CR_STAT_READS_SHIFT		0
+#define EUR_CR_MNE_CR_STAT_STATS			0x0D0C
+#define EUR_CR_MNE_CR_STAT_STATS_RST_MASK	0x000FFFF0UL
+#define EUR_CR_MNE_CR_STAT_STATS_RST_SHIFT	4
+#define EUR_CR_MNE_CR_STAT_STATS_SEL_MASK	0x0000000FUL
+#define EUR_CR_MNE_CR_STAT_STATS_SEL_SHIFT	0
+#define EUR_CR_MNE_CR_STAT_STATS_OUT				0x0D10
+#define EUR_CR_MNE_CR_STAT_STATS_OUT_VALUE_MASK		0xFFFFFFFFUL
+#define EUR_CR_MNE_CR_STAT_STATS_OUT_VALUE_SHIFT	0
+#define EUR_CR_MNE_CR_EVENT_STATUS				0x0D14
+#define EUR_CR_MNE_CR_EVENT_STATUS_INVAL_MASK	0x00000001UL
+#define EUR_CR_MNE_CR_EVENT_STATUS_INVAL_SHIFT	0
+#define EUR_CR_MNE_CR_EVENT_CLEAR				0x0D18
+#define EUR_CR_MNE_CR_EVENT_CLEAR_INVAL_MASK	0x00000001UL
+#define EUR_CR_MNE_CR_EVENT_CLEAR_INVAL_SHIFT	0
+#define EUR_CR_MNE_CR_CTRL_INVAL				0x0D20
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxdefs.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxdefs.h
new file mode 100644
index 0000000..c496765
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxdefs.h
@@ -0,0 +1,78 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _SGXDEFS_H_
+#define	_SGXDEFS_H_
+
+#include "sgxerrata.h"
+#include "sgxfeaturedefs.h"
+
+#if defined(SGX520)
+#include "sgx520defs.h"
+#else
+#if defined(SGX530)
+#include "sgx530defs.h"
+#else
+#if defined(SGX535)
+#include "sgx535defs.h"
+#else
+#if defined(SGX535_V1_1)
+#include "sgx535defs.h"
+#else
+#if defined(SGX540)
+#include "sgx540defs.h"
+#else
+#if defined(SGX541)
+#include "sgx541defs.h"
+#else
+#if defined(SGX543)
+#include "sgx543defs.h"
+#else
+#if defined(SGX545)
+#include "sgx545defs.h"
+#else
+#if defined(SGX531)
+#include "sgx531defs.h"
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#if defined(SGX_FEATURE_MP)
+#if defined(SGX541)
+#if SGX_CORE_REV == 100
+#include "sgx541_100mpdefs.h"
+#else
+#include "sgx541mpdefs.h"
+#endif
+#else
+#include "sgxmpdefs.h"
+#endif
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxerrata.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxerrata.h
new file mode 100644
index 0000000..dee5b43
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxerrata.h
@@ -0,0 +1,310 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _SGXERRATA_KM_H_
+#define _SGXERRATA_KM_H_
+
+#if defined(SGX520) && !defined(SGX_CORE_DEFINED)
+
+	#define SGX_CORE_REV_HEAD	0
+	#if defined(USE_SGX_CORE_REV_HEAD)
+
+		#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+	#endif
+
+	#if SGX_CORE_REV == 100
+		#define FIX_HW_BRN_28889
+	#else
+	#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+	#else
+		#error "sgxerrata.h: SGX520 Core Revision unspecified"
+	#endif
+	#endif
+
+	#define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX530) && !defined(SGX_CORE_DEFINED)
+
+	#define SGX_CORE_REV_HEAD	0
+	#if defined(USE_SGX_CORE_REV_HEAD)
+
+		#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+	#endif
+
+	#if SGX_CORE_REV == 103
+		#define FIX_HW_BRN_22934
+		#define FIX_HW_BRN_28889
+	#else
+	#if SGX_CORE_REV == 110
+		#define FIX_HW_BRN_22934
+		#define FIX_HW_BRN_28889
+	#else
+	#if SGX_CORE_REV == 111
+		#define FIX_HW_BRN_22934
+		#define FIX_HW_BRN_28889
+	#else
+	#if SGX_CORE_REV == 120
+		#define FIX_HW_BRN_22934
+		#define FIX_HW_BRN_28889
+	#else
+	#if SGX_CORE_REV == 121
+		#define FIX_HW_BRN_22934
+		#define FIX_HW_BRN_28889
+	#else
+	#if SGX_CORE_REV == 125
+		#define FIX_HW_BRN_22934
+		#define FIX_HW_BRN_28889
+	#else
+	#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+	#else
+		#error "sgxerrata.h: SGX530 Core Revision unspecified"
+	#endif
+	#endif
+	#endif
+	#endif
+	#endif
+#endif
+        #endif
+
+	#define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX531) && !defined(SGX_CORE_DEFINED)
+
+	#define SGX_CORE_REV_HEAD	0
+	#if defined(USE_SGX_CORE_REV_HEAD)
+
+		#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+	#endif
+
+	#if SGX_CORE_REV == 101
+		#define FIX_HW_BRN_26620
+		#define FIX_HW_BRN_28011
+	#else
+	#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+	#else
+		#error "sgxerrata.h: SGX531 Core Revision unspecified"
+	#endif
+	#endif
+
+	#define SGX_CORE_DEFINED
+#endif
+
+#if (defined(SGX535) || defined(SGX535_V1_1)) && !defined(SGX_CORE_DEFINED)
+
+	#define SGX_CORE_REV_HEAD	0
+	#if defined(USE_SGX_CORE_REV_HEAD)
+
+		#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+	#endif
+
+	#if SGX_CORE_REV == 111
+		#define FIX_HW_BRN_23281
+		#define FIX_HW_BRN_23410
+		#define FIX_HW_BRN_22693
+		#define FIX_HW_BRN_22934
+		#define FIX_HW_BRN_22997
+		#define FIX_HW_BRN_23030
+	#else
+	#if SGX_CORE_REV == 1111
+		#define FIX_HW_BRN_23281
+		#define FIX_HW_BRN_23410
+		#define FIX_HW_BRN_22693
+		#define FIX_HW_BRN_22934
+		#define FIX_HW_BRN_22997
+		#define FIX_HW_BRN_23030
+	#else
+	#if SGX_CORE_REV == 112
+		#define FIX_HW_BRN_23281
+		#define FIX_HW_BRN_23410
+		#define FIX_HW_BRN_22693
+		#define FIX_HW_BRN_22934
+		#define FIX_HW_BRN_22997
+		#define FIX_HW_BRN_23030
+	#else
+	#if SGX_CORE_REV == 113
+		#define FIX_HW_BRN_22934
+		#define FIX_HW_BRN_23281
+		#define FIX_HW_BRN_23944
+		#define FIX_HW_BRN_23410
+	#else
+	#if SGX_CORE_REV == 121
+		#define FIX_HW_BRN_22934
+		#define FIX_HW_BRN_23944
+		#define FIX_HW_BRN_23410
+	#else
+	#if SGX_CORE_REV == 126
+		#define FIX_HW_BRN_22934
+	#else
+	#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+	#else
+		#error "sgxerrata.h: SGX535 Core Revision unspecified"
+
+	#endif
+	#endif
+	#endif
+	#endif
+	#endif
+	#endif
+	#endif
+
+	#define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX540) && !defined(SGX_CORE_DEFINED)
+
+	#define SGX_CORE_REV_HEAD	0
+	#if defined(USE_SGX_CORE_REV_HEAD)
+
+		#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+	#endif
+
+	#if SGX_CORE_REV == 101
+		#define FIX_HW_BRN_25499
+		#define FIX_HW_BRN_25503
+		#define FIX_HW_BRN_26620
+		#define FIX_HW_BRN_28011
+	#else
+	#if SGX_CORE_REV == 110
+		#define FIX_HW_BRN_25503
+		#define FIX_HW_BRN_26620
+		#define FIX_HW_BRN_28011
+	#else
+	#if SGX_CORE_REV == 120
+		#define FIX_HW_BRN_26620
+		#define FIX_HW_BRN_28011
+	#else
+	#if SGX_CORE_REV == 121
+		#define FIX_HW_BRN_28011
+	#else
+	#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+	#else
+		#error "sgxerrata.h: SGX540 Core Revision unspecified"
+	#endif
+	#endif
+	#endif
+	#endif
+	#endif
+
+	#define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX541) && !defined(SGX_CORE_DEFINED)
+	#if defined(SGX_FEATURE_MP)
+
+		#define SGX_CORE_REV_HEAD	0
+		#if defined(USE_SGX_CORE_REV_HEAD)
+
+			#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+		#endif
+
+		#if SGX_CORE_REV == 100
+			#define FIX_HW_BRN_27270
+			#define FIX_HW_BRN_28011
+			#define FIX_HW_BRN_27510
+
+		#else
+		#if SGX_CORE_REV == 101
+
+		#else
+		#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+		#else
+			#error "sgxerrata.h: SGX541 Core Revision unspecified"
+		#endif
+		#endif
+		#endif
+
+		#define SGX_CORE_DEFINED
+	#else
+		#error "sgxerrata.h: SGX541 only supports MP configs (SGX_FEATURE_MP)"
+	#endif
+#endif
+
+#if defined(SGX543) && !defined(SGX_CORE_DEFINED)
+	#if defined(SGX_FEATURE_MP)
+
+		#define SGX_CORE_REV_HEAD	0
+		#if defined(USE_SGX_CORE_REV_HEAD)
+
+			#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+		#endif
+
+		#if SGX_CORE_REV == 100
+
+		#else
+		#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+		#else
+			#error "sgxerrata.h: SGX543 Core Revision unspecified"
+		#endif
+		#endif
+
+		#define SGX_CORE_DEFINED
+	#else
+		#error "sgxerrata.h: SGX543 only supports MP configs (SGX_FEATURE_MP)"
+	#endif
+#endif
+
+#if defined(SGX545) && !defined(SGX_CORE_DEFINED)
+
+	#define SGX_CORE_REV_HEAD	0
+	#if defined(USE_SGX_CORE_REV_HEAD)
+
+		#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+	#endif
+
+	#if SGX_CORE_REV == 100
+		#define FIX_HW_BRN_26620
+		#define FIX_HW_BRN_27266
+		#define FIX_HW_BRN_27456
+	#else
+	#if SGX_CORE_REV == 109
+
+	#else
+	#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+	#else
+		#error "sgxerrata.h: SGX545 Core Revision unspecified"
+	#endif
+	#endif
+	#endif
+
+	#define SGX_CORE_DEFINED
+#endif
+
+#if !defined(SGX_CORE_DEFINED)
+#if defined (__GNUC__)
+	#warning "sgxerrata.h: SGX Core Version unspecified"
+#else
+	#pragma message("sgxerrata.h: SGX Core Version unspecified")
+#endif
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h
new file mode 100644
index 0000000..0672ad6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h
@@ -0,0 +1,159 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if defined(SGX520)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX520"
+	#define SGX_CORE_ID										SGX_CORE_ID_520
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(28)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+#else
+#if defined(SGX530)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX530"
+	#define SGX_CORE_ID										SGX_CORE_ID_530
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(28)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+#else
+#if defined(SGX535)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX535"
+	#define SGX_CORE_ID										SGX_CORE_ID_535
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(32)
+	#define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+	#define SGX_FEATURE_BIF_NUM_DIRLISTS					(16)
+	#define SGX_FEATURE_2D_HARDWARE
+	#define SGX_FEATURE_AUTOCLOCKGATING
+	#define SUPPORT_SGX_GENERAL_MAPPING_HEAP
+	#define SUPPORT_SGX_VIDEO_HEAP
+#else
+#if defined(SGX540)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX540"
+	#define SGX_CORE_ID										SGX_CORE_ID_540
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(28)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+	#define SGX_FEATURE_MULTI_EVENT_KICK
+#else
+#if defined(SGX541)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX541"
+	#define SGX_CORE_ID										SGX_CORE_ID_541
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(32)
+	#define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+	#define SGX_FEATURE_BIF_NUM_DIRLISTS					(8)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+    #define SGX_FEATURE_SPM_MODE_0
+	#define SGX_FEATURE_MULTI_EVENT_KICK
+#else
+#if defined(SGX543)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX543"
+	#define SGX_CORE_ID										SGX_CORE_ID_543
+	#define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+	#define SGX_FEATURE_USE_UNLIMITED_PHASES
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(32)
+	#define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+	#define SGX_FEATURE_BIF_NUM_DIRLISTS					(8)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+	#define SGX_FEATURE_MONOLITHIC_UKERNEL
+	#define SGX_FEATURE_MULTI_EVENT_KICK
+	#define SGX_FEATURE_DATA_BREAKPOINTS
+#else
+#if defined(SGX531)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX531"
+	#define SGX_CORE_ID										SGX_CORE_ID_531
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(28)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+	#define SGX_FEATURE_MULTI_EVENT_KICK
+#else
+#if defined(SGX545)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX545"
+	#define SGX_CORE_ID										SGX_CORE_ID_545
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(32)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+	#define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+	#define SGX_FEATURE_USE_UNLIMITED_PHASES
+	#define SGX_FEATURE_VOLUME_TEXTURES
+	#define SGX_FEATURE_HOST_ALLOC_FROM_DPM
+	#define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+	#define SGX_FEATURE_BIF_NUM_DIRLISTS				(16)
+	#define SGX_FEATURE_NUM_USE_PIPES					(4)
+	#define	SGX_FEATURE_TEXTURESTRIDE_EXTENSION
+	#define SGX_FEATURE_PDS_DATA_INTERLEAVE_2DWORDS
+	#define SGX_FEATURE_MONOLITHIC_UKERNEL
+	#define SGX_FEATURE_ZLS_EXTERNALZ
+	#define SGX_FEATURE_VDM_CONTEXT_SWITCH_REV_2
+	#define SGX_FEATURE_ISP_CONTEXT_SWITCH_REV_2
+	#define SGX_FEATURE_NUM_PDS_PIPES					(2)
+	#define SGX_FEATURE_NATIVE_BACKWARD_BLIT
+	#define SGX_FEATURE_MAX_TA_RENDER_TARGETS				(512)
+	#define SGX_FEATURE_SPM_MODE_0
+	#define SGX_FEATURE_SECONDARY_REQUIRES_USE_KICK
+	#define SGX_FEATURE_DCU
+
+
+	#define SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS
+	#define SGX_FEATURE_MULTI_EVENT_KICK
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#if defined(FIX_HW_BRN_22693)
+#undef SGX_FEATURE_AUTOCLOCKGATING
+#endif
+
+#if defined(FIX_HW_BRN_27266)
+#undef SGX_FEATURE_36BIT_MMU
+#endif
+
+#if defined(FIX_HW_BRN_27456)
+#undef SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS
+#endif
+
+#if defined(FIX_HW_BRN_22934)	\
+	|| defined(FIX_HW_BRN_25499)
+#undef SGX_FEATURE_MULTI_EVENT_KICK
+#endif
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+	#if defined(SGX_FEATURE_36BIT_MMU)
+		#error SGX_FEATURE_SYSTEM_CACHE is incompatible with SGX_FEATURE_36BIT_MMU
+	#endif
+	#if defined(FIX_HW_BRN_26620) && !defined(SGX_FEATURE_MULTI_EVENT_KICK)
+		#define SGX_BYPASS_SYSTEM_CACHE
+	#endif
+#endif
+
+#if defined(SGX_FEATURE_MP)
+#if !defined(SGX_FEATURE_MP_CORE_COUNT)
+#error SGX_FEATURE_MP_CORE_COUNT must be defined when SGX_FEATURE_MP is defined
+#endif
+#else
+#define SGX_FEATURE_MP_CORE_COUNT	(1)
+#endif
+
+#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && !defined(SUPPORT_SGX_PRIORITY_SCHEDULING)
+#define SUPPORT_SGX_PRIORITY_SCHEDULING
+#endif
+
+#include "img_types.h"
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxmmu.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxmmu.h
new file mode 100644
index 0000000..c6b4c0d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/hwdefs/sgxmmu.h
@@ -0,0 +1,75 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__SGXMMU_KM_H__)
+#define __SGXMMU_KM_H__
+
+#define SGX_MMU_PAGE_SHIFT				(12)
+#define SGX_MMU_PAGE_SIZE				(1UL<<SGX_MMU_PAGE_SHIFT)
+#define SGX_MMU_PAGE_MASK				(SGX_MMU_PAGE_SIZE - 1UL)
+
+#define SGX_MMU_PD_SHIFT				(10)
+#define SGX_MMU_PD_SIZE					(1UL<<SGX_MMU_PD_SHIFT)
+#define SGX_MMU_PD_MASK					(0xFFC00000UL)
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+	#define SGX_MMU_PDE_ADDR_MASK			(0xFFFFFF00UL)
+	#define SGX_MMU_PDE_ADDR_ALIGNSHIFT		(4)
+#else
+	#define SGX_MMU_PDE_ADDR_MASK			(0xFFFFF000UL)
+	#define SGX_MMU_PDE_ADDR_ALIGNSHIFT		(0)
+#endif
+#define SGX_MMU_PDE_VALID				(0x00000001UL)
+#define SGX_MMU_PDE_PAGE_SIZE_4K		(0x00000000UL)
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+	#define SGX_MMU_PDE_PAGE_SIZE_16K		(0x00000002UL)
+	#define SGX_MMU_PDE_PAGE_SIZE_64K		(0x00000004UL)
+	#define SGX_MMU_PDE_PAGE_SIZE_256K		(0x00000006UL)
+	#define SGX_MMU_PDE_PAGE_SIZE_1M		(0x00000008UL)
+	#define SGX_MMU_PDE_PAGE_SIZE_4M		(0x0000000AUL)
+	#define SGX_MMU_PDE_PAGE_SIZE_MASK		(0x0000000EUL)
+#else
+	#define SGX_MMU_PDE_WRITEONLY			(0x00000002UL)
+	#define SGX_MMU_PDE_READONLY			(0x00000004UL)
+	#define SGX_MMU_PDE_CACHECONSISTENT		(0x00000008UL)
+	#define SGX_MMU_PDE_EDMPROTECT			(0x00000010UL)
+#endif
+
+#define SGX_MMU_PT_SHIFT				(10)
+#define SGX_MMU_PT_SIZE					(1UL<<SGX_MMU_PT_SHIFT)
+#define SGX_MMU_PT_MASK					(0x003FF000UL)
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+	#define SGX_MMU_PTE_ADDR_MASK			(0xFFFFFF00UL)
+	#define SGX_MMU_PTE_ADDR_ALIGNSHIFT		(4)
+#else
+	#define SGX_MMU_PTE_ADDR_MASK			(0xFFFFF000UL)
+	#define SGX_MMU_PTE_ADDR_ALIGNSHIFT		(0)
+#endif
+#define SGX_MMU_PTE_VALID				(0x00000001UL)
+#define SGX_MMU_PTE_WRITEONLY			(0x00000002UL)
+#define SGX_MMU_PTE_READONLY			(0x00000004UL)
+#define SGX_MMU_PTE_CACHECONSISTENT		(0x00000008UL)
+#define SGX_MMU_PTE_EDMPROTECT			(0x00000010UL)
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/buffer_manager.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/buffer_manager.h
new file mode 100644
index 0000000..c792292
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/buffer_manager.h
@@ -0,0 +1,214 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _BUFFER_MANAGER_H_
+#define _BUFFER_MANAGER_H_
+
+#include "img_types.h"
+#include "ra.h"
+#include "perproc.h"
+
+#if defined(__cplusplus)
+extern "C"{
+#endif
+
+typedef struct _BM_HEAP_ BM_HEAP;
+
+struct _BM_MAPPING_
+{
+	enum
+	{
+		hm_wrapped = 1,
+		hm_wrapped_scatter,
+		hm_wrapped_virtaddr,
+		hm_wrapped_scatter_virtaddr,
+		hm_env,
+		hm_contiguous
+	} eCpuMemoryOrigin;
+
+	BM_HEAP				*pBMHeap;
+	RA_ARENA			*pArena;
+
+	IMG_CPU_VIRTADDR	CpuVAddr;
+	IMG_CPU_PHYADDR		CpuPAddr;
+	IMG_DEV_VIRTADDR	DevVAddr;
+	IMG_SYS_PHYADDR		*psSysAddr;
+	IMG_SIZE_T			uSize;
+    IMG_HANDLE          hOSMemHandle;
+	IMG_UINT32			ui32Flags;
+};
+
+typedef struct _BM_BUF_
+{
+	IMG_CPU_VIRTADDR	*CpuVAddr;
+    IMG_VOID            *hOSMemHandle;
+	IMG_CPU_PHYADDR		CpuPAddr;
+	IMG_DEV_VIRTADDR	DevVAddr;
+
+	BM_MAPPING			*pMapping;
+	IMG_UINT32			ui32RefCount;
+	IMG_UINT32			ui32ExportCount;
+} BM_BUF;
+
+struct _BM_HEAP_
+{
+	IMG_UINT32				ui32Attribs;
+	BM_CONTEXT				*pBMContext;
+	RA_ARENA				*pImportArena;
+	RA_ARENA				*pLocalDevMemArena;
+	RA_ARENA				*pVMArena;
+	DEV_ARENA_DESCRIPTOR	sDevArena;
+	MMU_HEAP				*pMMUHeap;
+
+	struct _BM_HEAP_ 		*psNext;
+	struct _BM_HEAP_ 		**ppsThis;
+};
+
+struct _BM_CONTEXT_
+{
+	MMU_CONTEXT	*psMMUContext;
+
+
+	 BM_HEAP *psBMHeap;
+
+
+	 BM_HEAP *psBMSharedHeap;
+
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+
+	HASH_TABLE *pBufferHash;
+
+
+	IMG_HANDLE hResItem;
+
+	IMG_UINT32 ui32RefCount;
+
+
+
+	struct _BM_CONTEXT_ *psNext;
+	struct _BM_CONTEXT_ **ppsThis;
+};
+
+
+
+typedef IMG_VOID *BM_HANDLE;
+
+#define BP_POOL_MASK         0x7
+
+#define BP_CONTIGUOUS			(1 << 3)
+#define BP_PARAMBUFFER			(1 << 4)
+
+#define BM_MAX_DEVMEM_ARENAS  2
+
+IMG_HANDLE
+BM_CreateContext(PVRSRV_DEVICE_NODE			*psDeviceNode,
+				 IMG_DEV_PHYADDR			*psPDDevPAddr,
+				 PVRSRV_PER_PROCESS_DATA	*psPerProc,
+				 IMG_BOOL					*pbCreated);
+
+
+PVRSRV_ERROR
+BM_DestroyContext (IMG_HANDLE hBMContext,
+					IMG_BOOL *pbCreated);
+
+
+IMG_HANDLE
+BM_CreateHeap (IMG_HANDLE hBMContext,
+				DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo);
+
+IMG_VOID
+BM_DestroyHeap (IMG_HANDLE hDevMemHeap);
+
+
+IMG_BOOL
+BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_BOOL
+BM_Alloc (IMG_HANDLE			hDevMemHeap,
+			IMG_DEV_VIRTADDR	*psDevVAddr,
+			IMG_SIZE_T			uSize,
+			IMG_UINT32			*pui32Flags,
+			IMG_UINT32			uDevVAddrAlignment,
+			BM_HANDLE			*phBuf);
+
+IMG_BOOL
+BM_Wrap (	IMG_HANDLE hDevMemHeap,
+		    IMG_SIZE_T ui32Size,
+			IMG_SIZE_T ui32Offset,
+			IMG_BOOL bPhysContig,
+			IMG_SYS_PHYADDR *psSysAddr,
+			IMG_VOID *pvCPUVAddr,
+			IMG_UINT32 *pui32Flags,
+			BM_HANDLE *phBuf);
+
+IMG_VOID
+BM_Free (BM_HANDLE hBuf,
+		IMG_UINT32 ui32Flags);
+
+
+IMG_CPU_VIRTADDR
+BM_HandleToCpuVaddr (BM_HANDLE hBuf);
+
+IMG_DEV_VIRTADDR
+BM_HandleToDevVaddr (BM_HANDLE hBuf);
+
+IMG_SYS_PHYADDR
+BM_HandleToSysPaddr (BM_HANDLE hBuf);
+
+IMG_HANDLE
+BM_HandleToOSMemHandle (BM_HANDLE hBuf);
+
+IMG_BOOL
+BM_ContiguousStatistics (IMG_UINT32 uFlags,
+                         IMG_UINT32 *pTotalBytes,
+                         IMG_UINT32 *pAvailableBytes);
+
+
+IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+								IMG_DEV_VIRTADDR sDevVPageAddr,
+								IMG_DEV_PHYADDR *psDevPAddr);
+
+PVRSRV_ERROR BM_GetHeapInfo(IMG_HANDLE hDevMemHeap,
+							PVRSRV_HEAP_INFO *psHeapInfo);
+
+MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap);
+
+MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext);
+
+IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap);
+
+PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext);
+
+
+IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_VOID BM_Export(BM_HANDLE hBuf);
+
+IMG_VOID BM_FreeExport(BM_HANDLE hBuf, IMG_UINT32 ui32Flags);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/device.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/device.h
new file mode 100644
index 0000000..c7fa61c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/device.h
@@ -0,0 +1,274 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __DEVICE_H__
+#define __DEVICE_H__
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "ra.h"
+#include "resman.h"
+
+typedef struct _BM_CONTEXT_ BM_CONTEXT;
+
+typedef struct _MMU_HEAP_ MMU_HEAP;
+typedef struct _MMU_CONTEXT_ MMU_CONTEXT;
+
+#define PVRSRV_BACKINGSTORE_SYSMEM_CONTIG		(1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+0))
+#define PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG	(1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+1))
+#define PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG		(1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+2))
+#define PVRSRV_BACKINGSTORE_LOCALMEM_NONCONTIG	(1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+3))
+
+typedef IMG_UINT32 DEVICE_MEMORY_HEAP_TYPE;
+#define DEVICE_MEMORY_HEAP_PERCONTEXT		0
+#define DEVICE_MEMORY_HEAP_KERNEL			1
+#define DEVICE_MEMORY_HEAP_SHARED			2
+#define DEVICE_MEMORY_HEAP_SHARED_EXPORTED	3
+
+#define PVRSRV_DEVICE_NODE_FLAGS_PORT80DISPLAY	1
+#define PVRSRV_DEVICE_NODE_FLAGS_MMU_OPT_INV	2
+
+typedef struct _DEVICE_MEMORY_HEAP_INFO_
+{
+
+	IMG_UINT32				ui32HeapID;
+
+
+	IMG_CHAR				*pszName;
+
+
+	IMG_CHAR				*pszBSName;
+
+
+	IMG_DEV_VIRTADDR		sDevVAddrBase;
+
+
+	IMG_UINT32				ui32HeapSize;
+
+
+	IMG_UINT32				ui32Attribs;
+
+
+	DEVICE_MEMORY_HEAP_TYPE	DevMemHeapType;
+
+
+	IMG_HANDLE				hDevMemHeap;
+
+
+	RA_ARENA				*psLocalDevMemArena;
+
+
+	IMG_UINT32				ui32DataPageSize;
+
+} DEVICE_MEMORY_HEAP_INFO;
+
+typedef struct _DEVICE_MEMORY_INFO_
+{
+
+	IMG_UINT32				ui32AddressSpaceSizeLog2;
+
+
+
+
+	IMG_UINT32				ui32Flags;
+
+
+	IMG_UINT32				ui32HeapCount;
+
+
+	IMG_UINT32				ui32SyncHeapID;
+
+
+	IMG_UINT32				ui32MappingHeapID;
+
+
+	DEVICE_MEMORY_HEAP_INFO	*psDeviceMemoryHeap;
+
+
+    BM_CONTEXT				*pBMKernelContext;
+
+
+    BM_CONTEXT				*pBMContext;
+
+} DEVICE_MEMORY_INFO;
+
+
+typedef struct DEV_ARENA_DESCRIPTOR_TAG
+{
+	IMG_UINT32				ui32HeapID;
+
+	IMG_CHAR				*pszName;
+
+	IMG_DEV_VIRTADDR		BaseDevVAddr;
+
+	IMG_UINT32 				ui32Size;
+
+	DEVICE_MEMORY_HEAP_TYPE	DevMemHeapType;
+
+
+	IMG_UINT32				ui32DataPageSize;
+
+	DEVICE_MEMORY_HEAP_INFO	*psDeviceMemoryHeapInfo;
+
+} DEV_ARENA_DESCRIPTOR;
+
+typedef struct _SYS_DATA_TAG_ *PSYS_DATA;
+
+typedef struct _PVRSRV_DEVICE_NODE_
+{
+	PVRSRV_DEVICE_IDENTIFIER	sDevId;
+	IMG_UINT32					ui32RefCount;
+
+
+
+
+	PVRSRV_ERROR			(*pfnInitDevice) (IMG_VOID*);
+
+	PVRSRV_ERROR			(*pfnDeInitDevice) (IMG_VOID*);
+
+
+	PVRSRV_ERROR			(*pfnInitDeviceCompatCheck) (struct _PVRSRV_DEVICE_NODE_*);
+
+
+	PVRSRV_ERROR			(*pfnMMUInitialise)(struct _PVRSRV_DEVICE_NODE_*, MMU_CONTEXT**, IMG_DEV_PHYADDR*);
+	IMG_VOID				(*pfnMMUFinalise)(MMU_CONTEXT*);
+	IMG_VOID				(*pfnMMUInsertHeap)(MMU_CONTEXT*, MMU_HEAP*);
+	MMU_HEAP*				(*pfnMMUCreate)(MMU_CONTEXT*,DEV_ARENA_DESCRIPTOR*,RA_ARENA**);
+	IMG_VOID				(*pfnMMUDelete)(MMU_HEAP*);
+	IMG_BOOL				(*pfnMMUAlloc)(MMU_HEAP*pMMU,
+										   IMG_SIZE_T uSize,
+										   IMG_SIZE_T *pActualSize,
+										   IMG_UINT32 uFlags,
+										   IMG_UINT32 uDevVAddrAlignment,
+										   IMG_DEV_VIRTADDR *pDevVAddr);
+	IMG_VOID				(*pfnMMUFree)(MMU_HEAP*,IMG_DEV_VIRTADDR,IMG_UINT32);
+	IMG_VOID 				(*pfnMMUEnable)(MMU_HEAP*);
+	IMG_VOID				(*pfnMMUDisable)(MMU_HEAP*);
+	IMG_VOID				(*pfnMMUMapPages)(MMU_HEAP *pMMU,
+											  IMG_DEV_VIRTADDR devVAddr,
+											  IMG_SYS_PHYADDR SysPAddr,
+											  IMG_SIZE_T uSize,
+											  IMG_UINT32 ui32MemFlags,
+											  IMG_HANDLE hUniqueTag);
+	IMG_VOID				(*pfnMMUMapShadow)(MMU_HEAP            *pMMU,
+											   IMG_DEV_VIRTADDR    MapBaseDevVAddr,
+											   IMG_SIZE_T          uSize,
+											   IMG_CPU_VIRTADDR    CpuVAddr,
+											   IMG_HANDLE          hOSMemHandle,
+											   IMG_DEV_VIRTADDR    *pDevVAddr,
+											   IMG_UINT32 ui32MemFlags,
+											   IMG_HANDLE hUniqueTag);
+	IMG_VOID				(*pfnMMUUnmapPages)(MMU_HEAP *pMMU,
+												IMG_DEV_VIRTADDR dev_vaddr,
+												IMG_UINT32 ui32PageCount,
+												IMG_HANDLE hUniqueTag);
+
+	IMG_VOID				(*pfnMMUMapScatter)(MMU_HEAP *pMMU,
+												IMG_DEV_VIRTADDR DevVAddr,
+												IMG_SYS_PHYADDR *psSysAddr,
+												IMG_SIZE_T uSize,
+												IMG_UINT32 ui32MemFlags,
+												IMG_HANDLE hUniqueTag);
+
+	IMG_DEV_PHYADDR			(*pfnMMUGetPhysPageAddr)(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr);
+	IMG_DEV_PHYADDR			(*pfnMMUGetPDDevPAddr)(MMU_CONTEXT *pMMUContext);
+
+
+	IMG_BOOL				(*pfnDeviceISR)(IMG_VOID*);
+
+	IMG_VOID				*pvISRData;
+
+	IMG_UINT32 				ui32SOCInterruptBit;
+
+	IMG_VOID				(*pfnDeviceMISR)(IMG_VOID*);
+
+
+	IMG_VOID				(*pfnDeviceCommandComplete)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
+
+	IMG_BOOL				bReProcessDeviceCommandComplete;
+
+
+	DEVICE_MEMORY_INFO		sDevMemoryInfo;
+
+
+	IMG_VOID				*pvDevice;
+	IMG_UINT32				ui32pvDeviceSize;
+
+
+	PRESMAN_CONTEXT			hResManContext;
+
+
+	PSYS_DATA				psSysData;
+
+
+	RA_ARENA				*psLocalDevMemArena;
+
+	IMG_UINT32				ui32Flags;
+
+	struct _PVRSRV_DEVICE_NODE_	*psNext;
+	struct _PVRSRV_DEVICE_NODE_	**ppsThis;
+} PVRSRV_DEVICE_NODE;
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
+											  PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*),
+											  IMG_UINT32 ui32SOCInterruptBit,
+			 								  IMG_UINT32 *pui32DeviceIndex );
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice(IMG_UINT32 ui32DevIndex);
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccesful);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex);
+
+#if !defined(USE_CODE)
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PollForValueKM(volatile IMG_UINT32* pui32LinMemAddr,
+												   IMG_UINT32 ui32Value,
+												   IMG_UINT32 ui32Mask,
+												   IMG_UINT32 ui32Waitus,
+												   IMG_UINT32 ui32Tries);
+
+#endif
+
+
+#if defined (USING_ISR_INTERRUPTS)
+PVRSRV_ERROR IMG_CALLCONV PollForInterruptKM(IMG_UINT32 ui32Value,
+								IMG_UINT32 ui32Mask,
+								IMG_UINT32 ui32Waitus,
+								IMG_UINT32 ui32Tries);
+#endif
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData);
+IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData);
+IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData);
+IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/handle.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/handle.h
new file mode 100644
index 0000000..ffa952f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/handle.h
@@ -0,0 +1,378 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __HANDLE_H__
+#define __HANDLE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_types.h"
+#include "hash.h"
+#include "resman.h"
+
+typedef enum
+{
+	PVRSRV_HANDLE_TYPE_NONE = 0,
+	PVRSRV_HANDLE_TYPE_PERPROC_DATA,
+	PVRSRV_HANDLE_TYPE_DEV_NODE,
+	PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT,
+	PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+	PVRSRV_HANDLE_TYPE_MEM_INFO,
+	PVRSRV_HANDLE_TYPE_SYNC_INFO,
+	PVRSRV_HANDLE_TYPE_DISP_INFO,
+	PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+	PVRSRV_HANDLE_TYPE_BUF_INFO,
+	PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+	PVRSRV_HANDLE_TYPE_BUF_BUFFER,
+	PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT,
+	PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT,
+	PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT,
+	PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+	PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+	PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+	PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+	PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+	PVRSRV_HANDLE_TYPE_MMAP_INFO,
+	PVRSRV_HANDLE_TYPE_SOC_TIMER
+} PVRSRV_HANDLE_TYPE;
+
+typedef enum
+{
+
+	PVRSRV_HANDLE_ALLOC_FLAG_NONE = 		0,
+
+	PVRSRV_HANDLE_ALLOC_FLAG_SHARED = 		0x01,
+
+	PVRSRV_HANDLE_ALLOC_FLAG_MULTI = 		0x02,
+
+	PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE = 		0x04
+} PVRSRV_HANDLE_ALLOC_FLAG;
+
+struct _PVRSRV_HANDLE_BASE_;
+typedef struct _PVRSRV_HANDLE_BASE_ PVRSRV_HANDLE_BASE;
+
+#ifdef	PVR_SECURE_HANDLES
+extern PVRSRV_HANDLE_BASE *gpsKernelHandleBase;
+
+#define	KERNEL_HANDLE_BASE (gpsKernelHandleBase)
+
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag);
+
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent);
+
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle);
+
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor);
+
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize);
+
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase);
+
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle);
+
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase);
+
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID);
+
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID);
+
+#else
+
+#define KERNEL_HANDLE_BASE IMG_NULL
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+{
+	PVR_UNREFERENCED_PARAMETER(eType);
+	PVR_UNREFERENCED_PARAMETER(eFlag);
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	*phHandle = pvData;
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocSubHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+	PVR_UNREFERENCED_PARAMETER(eType);
+	PVR_UNREFERENCED_PARAMETER(eFlag);
+	PVR_UNREFERENCED_PARAMETER(hParent);
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	*phHandle = pvData;
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
+{
+	PVR_UNREFERENCED_PARAMETER(eType);
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	*phHandle = pvData;
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupHandleAnyType)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	*peType = PVRSRV_HANDLE_TYPE_NONE;
+
+	*ppvData = hHandle;
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+	PVR_UNREFERENCED_PARAMETER(eType);
+
+	*ppvData = hHandle;
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupSubHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+	PVR_UNREFERENCED_PARAMETER(eType);
+	PVR_UNREFERENCED_PARAMETER(hAncestor);
+
+	*ppvData = hHandle;
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetParentHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+	PVR_UNREFERENCED_PARAMETER(eType);
+	PVR_UNREFERENCED_PARAMETER(hHandle);
+
+	*phParent = IMG_NULL;
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupAndReleaseHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	PVR_UNREFERENCED_PARAMETER(eType);
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	*ppvData = hHandle;
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVReleaseHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	PVR_UNREFERENCED_PARAMETER(hHandle);
+	PVR_UNREFERENCED_PARAMETER(eType);
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVNewHandleBatch)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+	PVR_UNREFERENCED_PARAMETER(ui32BatchSize);
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVCommitHandleBatch)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVReleaseHandleBatch)
+#endif
+static INLINE
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVSetMaxHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+	PVR_UNREFERENCED_PARAMETER(ui32MaxHandle);
+
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetMaxHandle)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	return 0;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVEnableHandlePurging)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPurgeHandles)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocHandleBase)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
+{
+	*ppsBase = IMG_NULL;
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFreeHandleBase)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVHandleInit)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
+{
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVHandleDeInit)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
+{
+	return PVRSRV_OK;
+}
+
+#endif
+
+#define PVRSRVAllocHandleNR(psBase, phHandle, pvData, eType, eFlag) \
+	(IMG_VOID)PVRSRVAllocHandle(psBase, phHandle, pvData, eType, eFlag)
+
+#define PVRSRVAllocSubHandleNR(psBase, phHandle, pvData, eType, eFlag, hParent) \
+	(IMG_VOID)PVRSRVAllocSubHandle(psBase, phHandle, pvData, eType, eFlag, hParent)
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/hash.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/hash.h
new file mode 100644
index 0000000..26c8e44
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/hash.h
@@ -0,0 +1,69 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _HASH_H_
+#define _HASH_H_
+
+#include "img_types.h"
+#include "osfunc.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef IMG_UINT32 HASH_FUNC(IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+typedef IMG_BOOL HASH_KEY_COMP(IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+
+typedef struct _HASH_TABLE_ HASH_TABLE;
+
+IMG_UINT32 HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+
+IMG_BOOL HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+
+HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp);
+
+HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen);
+
+IMG_VOID HASH_Delete (HASH_TABLE *pHash);
+
+IMG_BOOL HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v);
+
+IMG_BOOL HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v);
+
+IMG_UINTPTR_T HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey);
+
+IMG_UINTPTR_T HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+
+IMG_UINTPTR_T HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey);
+
+IMG_UINTPTR_T HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+
+#ifdef HASH_TRACE
+IMG_VOID HASH_Dump (HASH_TABLE *pHash);
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/lists.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/lists.h
new file mode 100644
index 0000000..70ef61d
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/lists.h
@@ -0,0 +1,172 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __LISTS_UTILS__
+#define __LISTS_UTILS__
+
+#include <stdarg.h>
+#include "img_types.h"
+
+#define DECLARE_LIST_FOR_EACH(TYPE) \
+IMG_VOID List_##TYPE##_ForEach(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_FOR_EACH(TYPE) \
+IMG_VOID List_##TYPE##_ForEach(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))\
+{\
+	while(psHead)\
+	{\
+		pfnCallBack(psHead);\
+		psHead = psHead->psNext;\
+	}\
+}
+
+
+#define DECLARE_LIST_FOR_EACH_VA(TYPE) \
+IMG_VOID List_##TYPE##_ForEach_va(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_FOR_EACH_VA(TYPE) \
+IMG_VOID List_##TYPE##_ForEach_va(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode, va_list va), ...) \
+{\
+	va_list ap;\
+	while(psHead)\
+	{\
+		va_start(ap, pfnCallBack);\
+		pfnCallBack(psHead, ap);\
+		psHead = psHead->psNext;\
+		va_end(ap);\
+	}\
+}
+
+
+#define DECLARE_LIST_ANY(TYPE) \
+IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_ANY(TYPE) \
+IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode))\
+{ \
+	IMG_VOID *pResult;\
+	TYPE *psNextNode;\
+	pResult = IMG_NULL;\
+	psNextNode = psHead;\
+	while(psHead && !pResult)\
+	{\
+		psNextNode = psNextNode->psNext;\
+		pResult = pfnCallBack(psHead);\
+		psHead = psNextNode;\
+	}\
+	return pResult;\
+}
+
+
+#define DECLARE_LIST_ANY_VA(TYPE) \
+IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_ANY_VA(TYPE) \
+IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNode, va_list va), ...)\
+{\
+	va_list ap;\
+	TYPE *psNextNode;\
+	IMG_VOID* pResult = IMG_NULL;\
+	while(psHead && !pResult)\
+	{\
+		psNextNode = psHead->psNext;\
+		va_start(ap, pfnCallBack);\
+		pResult = pfnCallBack(psHead, ap);\
+		va_end(ap);\
+		psHead = psNextNode;\
+	}\
+	return pResult;\
+}
+
+#define DECLARE_LIST_ANY_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any(TYPE *psHead, RTYPE (*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_ANY_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any(TYPE *psHead, RTYPE (*pfnCallBack)(TYPE* psNode))\
+{ \
+	RTYPE result;\
+	TYPE *psNextNode;\
+	result = CONTINUE;\
+	psNextNode = psHead;\
+	while(psHead && result == CONTINUE)\
+	{\
+		psNextNode = psNextNode->psNext;\
+		result = pfnCallBack(psHead);\
+		psHead = psNextNode;\
+	}\
+	return result;\
+}
+
+
+#define DECLARE_LIST_ANY_VA_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any_va(TYPE *psHead, RTYPE(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_ANY_VA_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any_va(TYPE *psHead, RTYPE(*pfnCallBack)(TYPE* psNode, va_list va), ...)\
+{\
+	va_list ap;\
+	TYPE *psNextNode;\
+	RTYPE result = CONTINUE;\
+	while(psHead && result == CONTINUE)\
+	{\
+		psNextNode = psHead->psNext;\
+		va_start(ap, pfnCallBack);\
+		result = pfnCallBack(psHead, ap);\
+		va_end(ap);\
+		psHead = psNextNode;\
+	}\
+	return result;\
+}
+
+
+#define DECLARE_LIST_REMOVE(TYPE) \
+IMG_VOID List_##TYPE##_Remove(TYPE *psNode)
+
+#define IMPLEMENT_LIST_REMOVE(TYPE) \
+IMG_VOID List_##TYPE##_Remove(TYPE *psNode)\
+{\
+	(*psNode->ppsThis)=psNode->psNext;\
+	if(psNode->psNext)\
+	{\
+		psNode->psNext->ppsThis = psNode->ppsThis;\
+	}\
+}
+
+#define DECLARE_LIST_INSERT(TYPE) \
+IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)
+
+#define IMPLEMENT_LIST_INSERT(TYPE) \
+IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)\
+{\
+	psNewNode->ppsThis = ppsHead;\
+	psNewNode->psNext = *ppsHead;\
+	*ppsHead = psNewNode;\
+	if(psNewNode->psNext)\
+	{\
+		psNewNode->psNext->ppsThis = &(psNewNode->psNext);\
+	}\
+}
+
+
+#define IS_LAST_ELEMENT(x) ((x)->psNext == IMG_NULL)
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/metrics.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/metrics.h
new file mode 100644
index 0000000..1ea12de
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/metrics.h
@@ -0,0 +1,126 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _METRICS_
+#define _METRICS_
+
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+#if defined(DEBUG) || defined(TIMING)
+
+
+typedef struct
+{
+	IMG_UINT32 ui32Start;
+	IMG_UINT32 ui32Stop;
+	IMG_UINT32 ui32Total;
+	IMG_UINT32 ui32Count;
+} Temporal_Data;
+
+extern Temporal_Data asTimers[];
+
+extern IMG_UINT32 PVRSRVTimeNow(IMG_VOID);
+extern IMG_VOID   PVRSRVSetupMetricTimers(IMG_VOID *pvDevInfo);
+extern IMG_VOID   PVRSRVOutputMetricTotals(IMG_VOID);
+
+
+#define PVRSRV_TIMER_DUMMY				0
+
+#define PVRSRV_TIMER_EXAMPLE_1			1
+#define PVRSRV_TIMER_EXAMPLE_2			2
+
+
+#define PVRSRV_NUM_TIMERS		(PVRSRV_TIMER_EXAMPLE_2 + 1)
+
+#define PVRSRV_TIME_START(X)	{ \
+									asTimers[X].ui32Count += 1; \
+									asTimers[X].ui32Count |= 0x80000000L; \
+									asTimers[X].ui32Start = PVRSRVTimeNow(); \
+									asTimers[X].ui32Stop  = 0; \
+								}
+
+#define PVRSRV_TIME_SUSPEND(X)	{ \
+									asTimers[X].ui32Stop += PVRSRVTimeNow() - asTimers[X].ui32Start; \
+								}
+
+#define PVRSRV_TIME_RESUME(X)	{ \
+									asTimers[X].ui32Start = PVRSRVTimeNow(); \
+								}
+
+#define PVRSRV_TIME_STOP(X)		{ \
+									asTimers[X].ui32Stop  += PVRSRVTimeNow() - asTimers[X].ui32Start; \
+									asTimers[X].ui32Total += asTimers[X].ui32Stop; \
+									asTimers[X].ui32Count &= 0x7FFFFFFFL; \
+								}
+
+#define PVRSRV_TIME_RESET(X)	{ \
+									asTimers[X].ui32Start = 0; \
+									asTimers[X].ui32Stop  = 0; \
+									asTimers[X].ui32Total = 0; \
+									asTimers[X].ui32Count = 0; \
+								}
+
+
+#if defined(__sh__)
+
+#define TST_REG   ((volatile IMG_UINT8 *) (psDevInfo->pvSOCRegsBaseKM))
+
+#define TCOR_2    ((volatile IMG_UINT *)  (psDevInfo->pvSOCRegsBaseKM+28))
+#define TCNT_2    ((volatile IMG_UINT *)  (psDevInfo->pvSOCRegsBaseKM+32))
+#define TCR_2     ((volatile IMG_UINT16 *)(psDevInfo->pvSOCRegsBaseKM+36))
+
+#define TIMER_DIVISOR  4
+
+#endif
+
+
+
+
+
+#else
+
+
+
+#define PVRSRV_TIME_START(X)
+#define PVRSRV_TIME_SUSPEND(X)
+#define PVRSRV_TIME_RESUME(X)
+#define PVRSRV_TIME_STOP(X)
+#define PVRSRV_TIME_RESET(X)
+
+#define PVRSRVSetupMetricTimers(X)
+#define PVRSRVOutputMetricTotals()
+
+
+
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/osfunc.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/osfunc.h
new file mode 100644
index 0000000..7a0b064
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/osfunc.h
@@ -0,0 +1,483 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifdef DEBUG_RELEASE_BUILD
+#pragma optimize( "", off )
+#define DEBUG		1
+#endif
+
+#ifndef __OSFUNC_H__
+#define __OSFUNC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__) && defined(__KERNEL__)
+#include <linux/hardirq.h>
+#include <linux/string.h>
+#endif
+
+
+
+	#define PVRSRV_PAGEABLE_SELECT		PVRSRV_OS_PAGEABLE_HEAP
+
+#define KERNEL_ID			0xffffffffL
+#define POWER_MANAGER_ID	0xfffffffeL
+#define ISR_ID				0xfffffffdL
+#define TIMER_ID			0xfffffffcL
+
+
+#define HOST_PAGESIZE			OSGetPageSize
+#define HOST_PAGEMASK			(~(HOST_PAGESIZE()-1))
+#define HOST_PAGEALIGN(addr)	(((addr)+HOST_PAGESIZE()-1)&HOST_PAGEMASK)
+
+#define PVRSRV_OS_HEAP_MASK			0xf
+#define PVRSRV_OS_PAGEABLE_HEAP		0x1
+#define PVRSRV_OS_NON_PAGEABLE_HEAP	0x2
+
+
+IMG_UINT32 OSClockus(IMG_VOID);
+IMG_SIZE_T OSGetPageSize(IMG_VOID);
+PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData,
+								 IMG_UINT32 ui32Irq,
+								 IMG_CHAR *pszISRName,
+								 IMG_VOID *pvDeviceNode);
+PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq);
+PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData);
+IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_VOID* pvLinAddr);
+IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_SIZE_T ui32Size);
+IMG_VOID *OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE *phOSMemHandle);
+IMG_BOOL OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle);
+
+PVRSRV_ERROR OSReservePhys(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnReservePhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle);
+
+#if defined(SUPPORT_CPU_CACHED_BUFFERS)
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID);
+IMG_VOID OSFlushCPUCacheRangeKM(IMG_VOID *pvRangeAddrStart,
+						 	IMG_VOID *pvRangeAddrEnd);
+#endif
+
+#if defined(__linux__)
+PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr,
+									IMG_VOID *pvCpuVAddr,
+									IMG_SIZE_T ui32Bytes,
+									IMG_UINT32 ui32Flags,
+									IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr,
+									IMG_SIZE_T ui32Bytes,
+									IMG_UINT32 ui32Flags,
+									IMG_HANDLE hOSMemHandle);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSRegisterDiscontigMem)
+#endif
+static INLINE PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr,
+													IMG_VOID *pvCpuVAddr,
+													IMG_SIZE_T ui32Bytes,
+													IMG_UINT32 ui32Flags,
+													IMG_HANDLE *phOSMemHandle)
+{
+	PVR_UNREFERENCED_PARAMETER(pBasePAddr);
+	PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+	PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+	PVR_UNREFERENCED_PARAMETER(ui32Flags);
+	PVR_UNREFERENCED_PARAMETER(phOSMemHandle);
+
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSUnRegisterDiscontigMem)
+#endif
+static INLINE PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr,
+													IMG_SIZE_T ui32Bytes,
+													IMG_UINT32 ui32Flags,
+													IMG_HANDLE hOSMemHandle)
+{
+	PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+	PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+	PVR_UNREFERENCED_PARAMETER(ui32Flags);
+	PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+#endif
+
+
+#if defined(__linux__)
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSReserveDiscontigPhys(IMG_SYS_PHYADDR *pBasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle)
+{
+#if defined(__linux__)
+	*ppvCpuVAddr = IMG_NULL;
+	return OSRegisterDiscontigMem(pBasePAddr, *ppvCpuVAddr, ui32Bytes, ui32Flags, phOSMemHandle);
+#else
+	extern IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr(IMG_SYS_PHYADDR SysPAddr);
+
+
+	return OSReservePhys(SysSysPAddrToCpuPAddr(pBasePAddr[0]), ui32Bytes, ui32Flags, ppvCpuVAddr, phOSMemHandle);
+#endif
+}
+
+static INLINE PVRSRV_ERROR OSUnReserveDiscontigPhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+#if defined(__linux__)
+	OSUnRegisterDiscontigMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
+#endif
+
+	return PVRSRV_OK;
+}
+#else
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSReserveDiscontigPhys(IMG_SYS_PHYADDR *pBasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle)
+{
+	PVR_UNREFERENCED_PARAMETER(pBasePAddr);
+	PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+	PVR_UNREFERENCED_PARAMETER(ui32Flags);
+	PVR_UNREFERENCED_PARAMETER(ppvCpuVAddr);
+	PVR_UNREFERENCED_PARAMETER(phOSMemHandle);
+
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSUnReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSUnReserveDiscontigPhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+	PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+	PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+	PVR_UNREFERENCED_PARAMETER(ui32Flags);
+	PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+#endif
+
+PVRSRV_ERROR OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
+							IMG_VOID *pvCpuVAddr,
+							IMG_SIZE_T ui32Bytes,
+							IMG_UINT32 ui32Flags,
+							IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnRegisterMem(IMG_VOID *pvCpuVAddr,
+							IMG_SIZE_T ui32Bytes,
+							IMG_UINT32 ui32Flags,
+							IMG_HANDLE hOSMemHandle);
+
+
+
+#if defined(__linux__)
+PVRSRV_ERROR OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+							   IMG_UINTPTR_T ui32ByteOffset,
+							   IMG_SIZE_T ui32Bytes,
+							   IMG_UINT32 ui32Flags,
+							   IMG_HANDLE *phOSMemHandleRet);
+PVRSRV_ERROR OSReleaseSubMemHandle(IMG_HANDLE hOSMemHandle, IMG_UINT32 ui32Flags);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSGetSubMemHandle)
+#endif
+static INLINE PVRSRV_ERROR OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+											 IMG_UINTPTR_T ui32ByteOffset,
+											 IMG_SIZE_T ui32Bytes,
+											 IMG_UINT32 ui32Flags,
+											 IMG_HANDLE *phOSMemHandleRet)
+{
+	PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
+	PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+	PVR_UNREFERENCED_PARAMETER(ui32Flags);
+
+	*phOSMemHandleRet = hOSMemHandle;
+	return PVRSRV_OK;
+}
+
+static INLINE PVRSRV_ERROR OSReleaseSubMemHandle(IMG_HANDLE hOSMemHandle, IMG_UINT32 ui32Flags)
+{
+	PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+	PVR_UNREFERENCED_PARAMETER(ui32Flags);
+	return PVRSRV_OK;
+}
+#endif
+
+IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID);
+IMG_UINT32 OSGetCurrentThreadID( IMG_VOID );
+IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T ui32Size);
+
+PVRSRV_ERROR OSAllocPages_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_UINT32 ui32PageSize, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phPageAlloc);
+PVRSRV_ERROR OSFreePages(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hPageAlloc);
+
+
+#ifdef PVRSRV_LOG_MEMORY_ALLOCS
+	#define OSAllocMem(flags, size, linAddr, blockAlloc, logStr) \
+		(PVR_TRACE(("OSAllocMem(" #flags ", " #size ", " #linAddr ", " #blockAlloc "): " logStr " (size = 0x%lx)", size)), \
+			OSAllocMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__))
+
+	#define OSAllocPages(flags, size, pageSize, linAddr, pageAlloc) \
+		(PVR_TRACE(("OSAllocPages(" #flags ", " #size ", " #pageSize ", " #linAddr ", " #pageAlloc "): (size = 0x%lx)", size)), \
+			OSAllocPages_Impl(flags, size, pageSize, linAddr, pageAlloc))
+
+	#define OSFreeMem(flags, size, linAddr, blockAlloc) \
+		(PVR_TRACE(("OSFreeMem(" #flags ", " #size ", " #linAddr ", " #blockAlloc "): (pointer = 0x%X)", linAddr)), \
+			OSFreeMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__))
+#else
+	#define OSAllocMem(flags, size, linAddr, blockAlloc, logString) \
+		OSAllocMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__)
+
+	#define OSAllocPages OSAllocPages_Impl
+
+	#define OSFreeMem(flags, size, linAddr, blockAlloc) \
+			OSFreeMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__)
+#endif
+
+#ifdef PVRSRV_DEBUG_OS_MEMORY
+
+	PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+										IMG_UINT32 ui32Size,
+										IMG_PVOID *ppvCpuVAddr,
+										IMG_HANDLE *phBlockAlloc,
+										IMG_CHAR *pszFilename,
+										IMG_UINT32 ui32Line);
+
+	PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+									 IMG_UINT32 ui32Size,
+									 IMG_PVOID pvCpuVAddr,
+									 IMG_HANDLE hBlockAlloc,
+									 IMG_CHAR *pszFilename,
+									 IMG_UINT32 ui32Line);
+
+
+	typedef struct
+	{
+		IMG_UINT8 sGuardRegionBefore[8];
+		IMG_CHAR sFileName[128];
+		IMG_UINT32 uLineNo;
+		IMG_SIZE_T uSize;
+		IMG_SIZE_T uSizeParityCheck;
+		enum valid_tag
+		{	isFree = 0x277260FF,
+			isAllocated = 0x260511AA
+		} eValid;
+	} OSMEM_DEBUG_INFO;
+
+	#define TEST_BUFFER_PADDING_STATUS (sizeof(OSMEM_DEBUG_INFO))
+	#define TEST_BUFFER_PADDING_AFTER  (8)
+	#define TEST_BUFFER_PADDING (TEST_BUFFER_PADDING_STATUS + TEST_BUFFER_PADDING_AFTER)
+#else
+	#define OSAllocMem_Debug_Wrapper OSAllocMem_Debug_Linux_Memory_Allocations
+	#define OSFreeMem_Debug_Wrapper OSFreeMem_Debug_Linux_Memory_Allocations
+#endif
+
+#if defined(__linux__) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+	PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line);
+	PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line);
+
+	#define OSAllocMem_Debug_Linux_Memory_Allocations OSAllocMem_Impl
+	#define OSFreeMem_Debug_Linux_Memory_Allocations OSFreeMem_Impl
+#else
+	PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phBlockAlloc);
+	PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hBlockAlloc);
+
+	#define OSAllocMem_Debug_Linux_Memory_Allocations(flags, size, addr, blockAlloc, file, line) \
+		OSAllocMem_Impl(flags, size, addr, blockAlloc)
+	#define OSFreeMem_Debug_Linux_Memory_Allocations(flags, size, addr, blockAlloc, file, line) \
+		OSFreeMem_Impl(flags, size, addr, blockAlloc)
+#endif
+
+
+
+#if defined(__linux__)
+IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_SIZE_T ui32ByteOffset);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSMemHandleToCpuPAddr)
+#endif
+static INLINE IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(IMG_HANDLE hOSMemHandle, IMG_SIZE_T ui32ByteOffset)
+{
+	IMG_CPU_PHYADDR sCpuPAddr;
+	PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+	PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
+	sCpuPAddr.uiAddr = 0;
+	return sCpuPAddr;
+}
+#endif
+PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData);
+PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData);
+IMG_CHAR* OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc);
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_SIZE_T ui32Size, const IMG_CHAR *pszFormat, ...);
+#define OSStringLength(pszString) strlen(pszString)
+
+PVRSRV_ERROR OSEventObjectCreate(const IMG_CHAR *pszName,
+								 PVRSRV_EVENTOBJECT *psEventObject);
+PVRSRV_ERROR OSEventObjectDestroy(PVRSRV_EVENTOBJECT *psEventObject);
+PVRSRV_ERROR OSEventObjectSignal(IMG_HANDLE hOSEventKM);
+PVRSRV_ERROR OSEventObjectWait(IMG_HANDLE hOSEventKM);
+PVRSRV_ERROR OSEventObjectOpen(PVRSRV_EVENTOBJECT *psEventObject,
+											IMG_HANDLE *phOSEvent);
+PVRSRV_ERROR OSEventObjectClose(PVRSRV_EVENTOBJECT *psEventObject,
+											IMG_HANDLE hOSEventKM);
+
+
+PVRSRV_ERROR OSBaseAllocContigMemory(IMG_SIZE_T ui32Size, IMG_CPU_VIRTADDR *pLinAddr, IMG_CPU_PHYADDR *pPhysAddr);
+PVRSRV_ERROR OSBaseFreeContigMemory(IMG_SIZE_T ui32Size, IMG_CPU_VIRTADDR LinAddr, IMG_CPU_PHYADDR PhysAddr);
+
+IMG_PVOID MapUserFromKernel(IMG_PVOID pvLinAddrKM,IMG_SIZE_T ui32Size,IMG_HANDLE *phMemBlock);
+IMG_PVOID OSMapHWRegsIntoUserSpace(IMG_HANDLE hDevCookie, IMG_SYS_PHYADDR sRegAddr, IMG_UINT32 ulSize, IMG_PVOID *ppvProcess);
+IMG_VOID  OSUnmapHWRegsFromUserSpace(IMG_HANDLE hDevCookie, IMG_PVOID pvUserAddr, IMG_PVOID pvProcess);
+
+IMG_VOID  UnmapUserFromKernel(IMG_PVOID pvLinAddrUM, IMG_SIZE_T ui32Size, IMG_HANDLE hMemBlock);
+
+PVRSRV_ERROR OSMapPhysToUserSpace(IMG_HANDLE hDevCookie,
+								  IMG_SYS_PHYADDR sCPUPhysAddr,
+								  IMG_SIZE_T uiSizeInBytes,
+								  IMG_UINT32 ui32CacheFlags,
+								  IMG_PVOID *ppvUserAddr,
+								  IMG_SIZE_T *puiActualSize,
+								  IMG_HANDLE hMappingHandle);
+
+PVRSRV_ERROR OSUnmapPhysToUserSpace(IMG_HANDLE hDevCookie,
+									IMG_PVOID pvUserAddr,
+									IMG_PVOID pvProcess);
+
+PVRSRV_ERROR OSLockResource(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+PVRSRV_ERROR OSUnlockResource(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+IMG_BOOL OSIsResourceLocked(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource);
+PVRSRV_ERROR OSDestroyResource(PVRSRV_RESOURCE *psResource);
+IMG_VOID OSBreakResourceLock(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus);
+IMG_VOID OSReleaseThreadQuanta(IMG_VOID);
+IMG_UINT32 OSPCIReadDword(IMG_UINT32 ui32Bus, IMG_UINT32 ui32Dev, IMG_UINT32 ui32Func, IMG_UINT32 ui32Reg);
+IMG_VOID OSPCIWriteDword(IMG_UINT32 ui32Bus, IMG_UINT32 ui32Dev, IMG_UINT32 ui32Func, IMG_UINT32 ui32Reg, IMG_UINT32 ui32Value);
+
+#ifndef OSReadHWReg
+IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+#endif
+#ifndef OSWriteHWReg
+IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
+#endif
+
+typedef IMG_VOID (*PFN_TIMER_FUNC)(IMG_VOID*);
+IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout);
+PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer);
+PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer);
+PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer);
+
+PVRSRV_ERROR OSGetSysMemSize(IMG_SIZE_T *pui32Bytes);
+
+typedef enum _HOST_PCI_INIT_FLAGS_
+{
+	HOST_PCI_INIT_FLAG_BUS_MASTER	= 0x00000001,
+	HOST_PCI_INIT_FLAG_MSI		= 0x00000002,
+	HOST_PCI_INIT_FLAG_FORCE_I32 	= 0x7fffffff
+} HOST_PCI_INIT_FLAGS;
+
+struct _PVRSRV_PCI_DEV_OPAQUE_STRUCT_;
+typedef struct _PVRSRV_PCI_DEV_OPAQUE_STRUCT_ *PVRSRV_PCI_DEV_HANDLE;
+
+PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16DeviceID, HOST_PCI_INIT_FLAGS eFlags);
+PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags);
+PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ);
+IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData);
+
+IMG_VOID OSPanic(IMG_VOID);
+
+IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID);
+
+typedef enum _img_verify_test
+{
+	PVR_VERIFY_WRITE = 0,
+	PVR_VERIFY_READ
+} IMG_VERIFY_TEST;
+
+IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_SIZE_T ui32Bytes);
+
+PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess, IMG_VOID *pvDest, IMG_VOID *pvSrc, IMG_SIZE_T ui32Bytes);
+PVRSRV_ERROR OSCopyFromUser(IMG_PVOID pvProcess, IMG_VOID *pvDest, IMG_VOID *pvSrc, IMG_SIZE_T ui32Bytes);
+
+#if defined(__linux__)
+PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID* pvCPUVAddr,
+									IMG_SIZE_T ui32Bytes,
+									IMG_SYS_PHYADDR *psSysPAddr,
+									IMG_HANDLE *phOSWrapMem,
+									IMG_BOOL bWrapWorkaround);
+PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSAcquirePhysPageAddr)
+#endif
+static INLINE PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID* pvCPUVAddr,
+												IMG_SIZE_T ui32Bytes,
+												IMG_SYS_PHYADDR *psSysPAddr,
+												IMG_HANDLE *phOSWrapMem,
+												IMG_BOOL bWrapWorkaround)
+{
+	PVR_UNREFERENCED_PARAMETER(pvCPUVAddr);
+	PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+	PVR_UNREFERENCED_PARAMETER(psSysPAddr);
+	PVR_UNREFERENCED_PARAMETER(phOSWrapMem);
+	PVR_UNREFERENCED_PARAMETER(bWrapWorkaround);
+	return PVRSRV_OK;
+}
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReleasePhysPageAddr)
+#endif
+static INLINE PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
+{
+	PVR_UNREFERENCED_PARAMETER(hOSWrapMem);
+	return PVRSRV_OK;
+}
+#endif
+
+#if defined(__linux__) && defined(__KERNEL__)
+#define	OS_SUPPORTS_IN_LISR
+static inline IMG_BOOL OSInLISR(IMG_VOID unref__ *pvSysData)
+{
+	return in_irq();
+}
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/osperproc.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/osperproc.h
new file mode 100644
index 0000000..a23b983
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/osperproc.h
@@ -0,0 +1,72 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __OSPERPROC_H__
+#define __OSPERPROC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__)
+PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData);
+PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData);
+
+PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessPrivateDataInit)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
+{
+	PVR_UNREFERENCED_PARAMETER(phOsPrivateData);
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessPrivateDataDeInit)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
+{
+	PVR_UNREFERENCED_PARAMETER(hOsPrivateData);
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessSetHandleOptions)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+	PVR_UNREFERENCED_PARAMETER(psHandleBase);
+
+	return PVRSRV_OK;
+}
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/pdump_km.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/pdump_km.h
new file mode 100644
index 0000000..31f7aa2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/pdump_km.h
@@ -0,0 +1,448 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _PDUMP_KM_H_
+#define _PDUMP_KM_H_
+
+#if defined(LINUX)
+#define COMMON_PDUMP_OS_SUPPORT
+#endif
+
+#if defined(COMMON_PDUMP_OS_SUPPORT)
+#if defined(SUPPORT_SGX) || defined(SUPPORT_MSVDX)
+#define SGX_SUPPORT_COMMON_PDUMP
+#if defined(SGX_SUPPORT_COMMON_PDUMP)
+#include <pdump_osfunc.h>
+#endif
+
+#endif
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define PDUMP_FLAGS_NEVER			0x08000000UL
+#define PDUMP_FLAGS_TOOUT2MEM		0x10000000UL
+#define PDUMP_FLAGS_LASTFRAME		0x20000000UL
+#define PDUMP_FLAGS_RESETLFBUFFER	0x40000000UL
+#define PDUMP_FLAGS_CONTINUOUS		0x80000000UL
+
+#define PDUMP_PD_UNIQUETAG			(IMG_HANDLE)0
+#define PDUMP_PT_UNIQUETAG			(IMG_HANDLE)0
+
+#define PDUMP_STREAM_PARAM2			0
+#define PDUMP_STREAM_SCRIPT2		1
+#define PDUMP_STREAM_DRIVERINFO		2
+#define PDUMP_NUM_STREAMS			3
+
+
+#ifndef PDUMP
+#define MAKEUNIQUETAG(hMemInfo)	(0)
+#endif
+
+#ifdef PDUMP
+
+#define MAKEUNIQUETAG(hMemInfo)	(((BM_BUF *)(((PVRSRV_KERNEL_MEM_INFO *)hMemInfo)->sMemBlk.hBuffer))->pMapping)
+
+	IMG_IMPORT PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+										  IMG_UINT32			ui32Offset,
+										  IMG_UINT32			ui32Value,
+										  IMG_UINT32			ui32Mask,
+										  PDUMP_POLL_OPERATOR	eOperator,
+										  IMG_UINT32			ui32Flags,
+										  IMG_HANDLE			hUniqueTag);
+
+	IMG_IMPORT PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psProcData,
+									   IMG_PVOID			pvAltLinAddr,
+									   IMG_PVOID			pvLinAddr,
+									   PVRSRV_KERNEL_MEM_INFO	*psMemInfo,
+									   IMG_UINT32			ui32Offset,
+									   IMG_UINT32			ui32Bytes,
+									   IMG_UINT32			ui32Flags,
+									   IMG_HANDLE			hUniqueTag);
+
+	IMG_IMPORT PVRSRV_ERROR PDumpMemKM(IMG_PVOID			pvAltLinAddr,
+									   PVRSRV_KERNEL_MEM_INFO	*psMemInfo,
+									   IMG_UINT32			ui32Offset,
+									   IMG_UINT32			ui32Bytes,
+									   IMG_UINT32			ui32Flags,
+									   IMG_HANDLE			hUniqueTag);
+	PVRSRV_ERROR PDumpMemPagesKM(PVRSRV_DEVICE_TYPE	eDeviceType,
+								 IMG_DEV_PHYADDR		*pPages,
+								 IMG_UINT32			ui32NumPages,
+								 IMG_DEV_VIRTADDR	sDevAddr,
+								 IMG_UINT32			ui32Start,
+								 IMG_UINT32			ui32Length,
+								 IMG_UINT32			ui32Flags,
+								 IMG_HANDLE			hUniqueTag);
+
+	PVRSRV_ERROR PDumpMem2KM(PVRSRV_DEVICE_TYPE	eDeviceType,
+							 IMG_CPU_VIRTADDR	pvLinAddr,
+							 IMG_UINT32			ui32Bytes,
+							 IMG_UINT32			ui32Flags,
+							 IMG_BOOL			bInitialisePages,
+							 IMG_HANDLE			hUniqueTag1,
+							 IMG_HANDLE			hUniqueTag2);
+	IMG_VOID PDumpInitCommon(IMG_VOID);
+	IMG_VOID PDumpDeInitCommon(IMG_VOID);
+	IMG_VOID PDumpInit(IMG_VOID);
+	IMG_VOID PDumpDeInit(IMG_VOID);
+	PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID);
+	PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID);
+	IMG_IMPORT PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame);
+	IMG_IMPORT PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags);
+	IMG_IMPORT PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags);
+
+	PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_UINT32 ui32RegAddr,
+									 IMG_UINT32 ui32RegValue,
+									 IMG_UINT32 ui32Flags);
+	PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_UINT32 ui32RegAddr,
+										IMG_UINT32 ui32RegValue,
+										IMG_UINT32 ui32Mask,
+										IMG_UINT32 ui32Flags);
+	PVRSRV_ERROR PDumpRegPolKM(IMG_UINT32 ui32RegAddr,
+							   IMG_UINT32 ui32RegValue,
+							   IMG_UINT32 ui32Mask);
+
+	IMG_IMPORT PVRSRV_ERROR PDumpBitmapKM(IMG_CHAR *pszFileName,
+										  IMG_UINT32 ui32FileOffset,
+										  IMG_UINT32 ui32Width,
+										  IMG_UINT32 ui32Height,
+										  IMG_UINT32 ui32StrideInBytes,
+										  IMG_DEV_VIRTADDR sDevBaseAddr,
+										  IMG_UINT32 ui32Size,
+										  PDUMP_PIXEL_FORMAT ePixelFormat,
+										  PDUMP_MEM_FORMAT eMemFormat,
+										  IMG_UINT32 ui32PDumpFlags);
+	IMG_IMPORT PVRSRV_ERROR PDumpReadRegKM(IMG_CHAR *pszFileName,
+										   IMG_UINT32 ui32FileOffset,
+										   IMG_UINT32 ui32Address,
+										   IMG_UINT32 ui32Size,
+										   IMG_UINT32 ui32PDumpFlags);
+
+	IMG_BOOL PDumpIsSuspended(IMG_VOID);
+
+#if defined(SGX_SUPPORT_COMMON_PDUMP) || !defined(SUPPORT_VGX)
+
+	PVRSRV_ERROR PDumpRegKM(IMG_UINT32		dwReg,
+							IMG_UINT32		dwData);
+	PVRSRV_ERROR PDumpComment(IMG_CHAR* pszFormat, ...);
+	PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32	ui32Flags,
+									   IMG_CHAR*	pszFormat,
+									   ...);
+
+	PVRSRV_ERROR PDumpPDReg(IMG_UINT32	ui32Reg,
+							IMG_UINT32	ui32dwData,
+							IMG_HANDLE	hUniqueTag);
+	PVRSRV_ERROR PDumpPDRegWithFlags(IMG_UINT32		ui32Reg,
+									 IMG_UINT32		ui32Data,
+									 IMG_UINT32		ui32Flags,
+									 IMG_HANDLE		hUniqueTag);
+#else
+	IMG_VOID PDumpRegKM(IMG_UINT32		dwReg,
+							IMG_UINT32		dwData);
+	IMG_VOID PDumpComment(IMG_CHAR* pszFormat, ...);
+	IMG_VOID PDumpCommentWithFlags(IMG_UINT32	ui32Flags,
+									   IMG_CHAR*	pszFormat,
+									   ...);
+
+
+	IMG_VOID PDumpPDReg(IMG_UINT32	ui32Reg,
+							IMG_UINT32	ui32dwData,
+							IMG_HANDLE	hUniqueTag);
+	IMG_VOID PDumpPDRegWithFlags(IMG_UINT32		ui32Reg,
+									 IMG_UINT32		ui32Data,
+									 IMG_UINT32		ui32Flags,
+									 IMG_HANDLE		hUniqueTag);
+#endif
+
+	IMG_VOID PDumpMsvdxRegRead(const IMG_CHAR* const	pRegRegion,
+							   const IMG_UINT32		dwRegOffset);
+
+	IMG_VOID PDumpMsvdxRegWrite(const IMG_CHAR* const	pRegRegion,
+								const IMG_UINT32		dwRegOffset,
+								const IMG_UINT32		dwData);
+
+	PVRSRV_ERROR PDumpMsvdxRegPol(const IMG_CHAR* const	pRegRegion,
+								  const IMG_UINT32		ui32Offset,
+								  const IMG_UINT32		ui32CheckFuncIdExt,
+								  const IMG_UINT32		ui32RequValue,
+								  const IMG_UINT32		ui32Enable,
+								  const IMG_UINT32		ui32PollCount,
+								  const IMG_UINT32		ui32TimeOut);
+
+	PVRSRV_ERROR  PDumpMsvdxWriteRef(const IMG_CHAR* const	pRegRegion,
+									 const IMG_UINT32		ui32VLROffset,
+									 const IMG_UINT32		ui32Physical );
+
+	IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID);
+	IMG_IMPORT IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID);
+
+	IMG_VOID PDumpMallocPagesPhys(PVRSRV_DEVICE_TYPE	eDeviceType,
+								  IMG_UINT32			ui32DevVAddr,
+								  IMG_PUINT32			pui32PhysPages,
+								  IMG_UINT32			ui32NumPages,
+								  IMG_HANDLE			hUniqueTag);
+	PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+									IMG_CHAR *pszMemSpace,
+									IMG_UINT32 *pui32MMUContextID,
+									IMG_UINT32 ui32MMUType,
+									IMG_HANDLE hUniqueTag1,
+									IMG_VOID *pvPDCPUAddr);
+	PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+									IMG_CHAR *pszMemSpace,
+									IMG_UINT32 ui32MMUContextID,
+									IMG_UINT32 ui32MMUType);
+
+	PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+								   IMG_UINT32 ui32Offset,
+								   IMG_DEV_PHYADDR sPDDevPAddr,
+								   IMG_HANDLE hUniqueTag1,
+								   IMG_HANDLE hUniqueTag2);
+
+	IMG_BOOL PDumpTestNextFrame(IMG_UINT32 ui32CurrentFrame);
+
+
+#if defined (COMMON_PDUMP_OS_SUPPORT) && !defined(SUPPORT_VGX)
+
+	PVRSRV_ERROR PDumpTASignatureRegisters(IMG_UINT32	ui32DumpFrameNum,
+								   IMG_UINT32	ui32TAKickCount,
+								   IMG_BOOL		bLastFrame,
+								   IMG_UINT32 *pui32Registers,
+								   IMG_UINT32 ui32NumRegisters);
+
+	PVRSRV_ERROR PDump3DSignatureRegisters(IMG_UINT32 ui32DumpFrameNum,
+															IMG_BOOL bLastFrame,
+															IMG_UINT32 *pui32Registers,
+															IMG_UINT32 ui32NumRegisters);
+
+	PVRSRV_ERROR PDumpCounterRegisters(IMG_UINT32 ui32DumpFrameNum,
+					IMG_BOOL		bLastFrame,
+					IMG_UINT32 *pui32Registers,
+					IMG_UINT32 ui32NumRegisters);
+
+	PVRSRV_ERROR PDumpRegRead(const IMG_UINT32 dwRegOffset, IMG_UINT32	ui32Flags);
+
+	PVRSRV_ERROR PDumpCycleCountRegRead(const IMG_UINT32 dwRegOffset, IMG_BOOL bLastFrame);
+
+	PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags);
+	PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks);
+
+	PVRSRV_ERROR PDumpMallocPages(PVRSRV_DEVICE_TYPE	eDeviceType,
+							  IMG_UINT32			ui32DevVAddr,
+							  IMG_CPU_VIRTADDR		pvLinAddr,
+							  IMG_HANDLE			hOSMemHandle,
+							  IMG_UINT32			ui32NumBytes,
+							  IMG_UINT32			ui32PageSize,
+							  IMG_HANDLE			hUniqueTag);
+	PVRSRV_ERROR PDumpMallocPageTable(PVRSRV_DEVICE_TYPE	eDeviceType,
+								  IMG_CPU_VIRTADDR		pvLinAddr,
+								  IMG_UINT32			ui32NumBytes,
+								  IMG_HANDLE			hUniqueTag);
+	PVRSRV_ERROR PDumpFreePages(struct _BM_HEAP_	*psBMHeap,
+							IMG_DEV_VIRTADDR	sDevVAddr,
+							IMG_UINT32			ui32NumBytes,
+							IMG_UINT32			ui32PageSize,
+							IMG_HANDLE      	hUniqueTag,
+							IMG_BOOL			bInterleaved);
+	PVRSRV_ERROR PDumpFreePageTable(PVRSRV_DEVICE_TYPE	eDeviceType,
+								IMG_CPU_VIRTADDR	pvLinAddr,
+								IMG_UINT32			ui32NumBytes,
+								IMG_HANDLE			hUniqueTag);
+
+	IMG_IMPORT PVRSRV_ERROR PDumpHWPerfCBKM(IMG_CHAR			*pszFileName,
+										IMG_UINT32			ui32FileOffset,
+										IMG_DEV_VIRTADDR	sDevBaseAddr,
+										IMG_UINT32 			ui32Size,
+										IMG_UINT32 			ui32PDumpFlags);
+
+	PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO	psROffMemInfo,
+				  IMG_UINT32				ui32ROffOffset,
+				  IMG_UINT32				ui32WPosVal,
+				  IMG_UINT32				ui32PacketSize,
+				  IMG_UINT32				ui32BufferSize,
+				  IMG_UINT32				ui32Flags,
+				  IMG_HANDLE				hUniqueTag);
+
+#else
+	IMG_VOID PDumpTASignatureRegisters(IMG_UINT32	ui32DumpFrameNum,
+			   IMG_UINT32	ui32TAKickCount,
+			   IMG_BOOL		bLastFrame,
+			   IMG_UINT32 *pui32Registers,
+			   IMG_UINT32 ui32NumRegisters);
+	IMG_VOID PDump3DSignatureRegisters(IMG_UINT32 ui32DumpFrameNum,
+			IMG_BOOL bLastFrame,
+			IMG_UINT32 *pui32Registers,
+			IMG_UINT32 ui32NumRegisters);
+	IMG_VOID PDumpCounterRegisters(IMG_UINT32 ui32DumpFrameNum,
+			IMG_BOOL		bLastFrame,
+			IMG_UINT32 *pui32Registers,
+			IMG_UINT32 ui32NumRegisters);
+
+	IMG_VOID PDumpRegRead(const IMG_UINT32 dwRegOffset, IMG_UINT32	ui32Flags);
+	IMG_VOID PDumpCycleCountRegRead(const IMG_UINT32 dwRegOffset, IMG_BOOL bLastFrame);
+
+	IMG_VOID PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags);
+	IMG_VOID PDumpIDL(IMG_UINT32 ui32Clocks);
+
+
+	IMG_VOID PDumpMallocPages(PVRSRV_DEVICE_TYPE	eDeviceType,
+							  IMG_UINT32			ui32DevVAddr,
+							  IMG_CPU_VIRTADDR		pvLinAddr,
+							  IMG_HANDLE			hOSMemHandle,
+							  IMG_UINT32			ui32NumBytes,
+							  IMG_UINT32			ui32PageSize,
+							  IMG_HANDLE			hUniqueTag);
+	IMG_VOID PDumpMallocPageTable(PVRSRV_DEVICE_TYPE	eDeviceType,
+								  IMG_CPU_VIRTADDR		pvLinAddr,
+								  IMG_UINT32			ui32NumBytes,
+								  IMG_HANDLE			hUniqueTag);
+	IMG_VOID PDumpFreePages(struct _BM_HEAP_	*psBMHeap,
+							IMG_DEV_VIRTADDR	sDevVAddr,
+							IMG_UINT32			ui32NumBytes,
+							IMG_UINT32			ui32PageSize,
+							IMG_HANDLE      	hUniqueTag,
+							IMG_BOOL			bInterleaved);
+	IMG_VOID PDumpFreePageTable(PVRSRV_DEVICE_TYPE	eDeviceType,
+								IMG_CPU_VIRTADDR	pvLinAddr,
+								IMG_UINT32			ui32NumBytes,
+								IMG_HANDLE			hUniqueTag);
+
+	IMG_IMPORT IMG_VOID PDumpHWPerfCBKM(IMG_CHAR			*pszFileName,
+										IMG_UINT32			ui32FileOffset,
+										IMG_DEV_VIRTADDR	sDevBaseAddr,
+										IMG_UINT32 			ui32Size,
+										IMG_UINT32 			ui32PDumpFlags);
+
+	IMG_VOID PDumpCBP(PPVRSRV_KERNEL_MEM_INFO	psROffMemInfo,
+				  IMG_UINT32				ui32ROffOffset,
+				  IMG_UINT32				ui32WPosVal,
+				  IMG_UINT32				ui32PacketSize,
+				  IMG_UINT32				ui32BufferSize,
+				  IMG_UINT32				ui32Flags,
+				  IMG_HANDLE				hUniqueTag);
+
+#endif
+
+	IMG_VOID PDumpVGXMemToFile(IMG_CHAR *pszFileName,
+							   IMG_UINT32 ui32FileOffset,
+							   PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+							   IMG_UINT32 uiAddr,
+							   IMG_UINT32 ui32Size,
+							   IMG_UINT32 ui32PDumpFlags,
+							   IMG_HANDLE hUniqueTag);
+
+	IMG_VOID PDumpSuspendKM(IMG_VOID);
+	IMG_VOID PDumpResumeKM(IMG_VOID);
+
+	#define PDUMPMEMPOL				PDumpMemPolKM
+	#define PDUMPMEM				PDumpMemKM
+	#define PDUMPMEM2				PDumpMem2KM
+	#define PDUMPMEMUM				PDumpMemUM
+	#define PDUMPINIT				PDumpInitCommon
+	#define PDUMPDEINIT				PDumpDeInitCommon
+	#define PDUMPISLASTFRAME		PDumpIsLastCaptureFrameKM
+	#define PDUMPTESTFRAME			PDumpIsCaptureFrameKM
+	#define PDUMPTESTNEXTFRAME		PDumpTestNextFrame
+	#define PDUMPREGWITHFLAGS		PDumpRegWithFlagsKM
+	#define PDUMPREG				PDumpRegKM
+	#define PDUMPCOMMENT			PDumpComment
+	#define PDUMPCOMMENTWITHFLAGS	PDumpCommentWithFlags
+	#define PDUMPREGPOL				PDumpRegPolKM
+	#define PDUMPREGPOLWITHFLAGS	PDumpRegPolWithFlagsKM
+	#define PDUMPMALLOCPAGES		PDumpMallocPages
+	#define PDUMPMALLOCPAGETABLE	PDumpMallocPageTable
+	#define PDUMPSETMMUCONTEXT		PDumpSetMMUContext
+	#define PDUMPCLEARMMUCONTEXT	PDumpClearMMUContext
+	#define PDUMPFREEPAGES			PDumpFreePages
+	#define PDUMPFREEPAGETABLE		PDumpFreePageTable
+	#define PDUMPPDREG				PDumpPDReg
+	#define PDUMPPDREGWITHFLAGS		PDumpPDRegWithFlags
+	#define PDUMPCBP				PDumpCBP
+	#define PDUMPMALLOCPAGESPHYS	PDumpMallocPagesPhys
+	#define PDUMPENDINITPHASE		PDumpStopInitPhaseKM
+	#define PDUMPMSVDXREGWRITE		PDumpMsvdxRegWrite
+	#define PDUMPMSVDXREGREAD		PDumpMsvdxRegRead
+	#define PDUMPMSVDXPOL			PDumpMsvdxRegPol
+	#define PDUMPMSVDXWRITEREF		PDumpMsvdxWriteRef
+	#define PDUMPBITMAPKM			PDumpBitmapKM
+	#define PDUMPDRIVERINFO			PDumpDriverInfoKM
+	#define PDUMPIDLWITHFLAGS		PDumpIDLWithFlags
+	#define PDUMPIDL				PDumpIDL
+	#define PDUMPSUSPEND			PDumpSuspendKM
+	#define PDUMPRESUME				PDumpResumeKM
+
+#else
+		#if ((defined(LINUX) || defined(GCC_IA32)) || defined(GCC_ARM))
+			#define PDUMPMEMPOL(args...)
+			#define PDUMPMEM(args...)
+			#define PDUMPMEM2(args...)
+			#define PDUMPMEMUM(args...)
+			#define PDUMPINIT(args...)
+			#define PDUMPDEINIT(args...)
+			#define PDUMPISLASTFRAME(args...)
+			#define PDUMPTESTFRAME(args...)
+			#define PDUMPTESTNEXTFRAME(args...)
+			#define PDUMPREGWITHFLAGS(args...)
+			#define PDUMPREG(args...)
+			#define PDUMPCOMMENT(args...)
+			#define PDUMPREGPOL(args...)
+			#define PDUMPREGPOLWITHFLAGS(args...)
+			#define PDUMPMALLOCPAGES(args...)
+			#define PDUMPMALLOCPAGETABLE(args...)
+			#define PDUMPSETMMUCONTEXT(args...)
+			#define PDUMPCLEARMMUCONTEXT(args...)
+			#define PDUMPFREEPAGES(args...)
+			#define PDUMPFREEPAGETABLE(args...)
+			#define PDUMPPDREG(args...)
+			#define PDUMPPDREGWITHFLAGS(args...)
+			#define PDUMPSYNC(args...)
+			#define PDUMPCOPYTOMEM(args...)
+			#define PDUMPWRITE(args...)
+			#define PDUMPCBP(args...)
+			#define PDUMPCOMMENTWITHFLAGS(args...)
+			#define PDUMPMALLOCPAGESPHYS(args...)
+			#define PDUMPENDINITPHASE(args...)
+			#define PDUMPMSVDXREG(args...)
+			#define PDUMPMSVDXREGWRITE(args...)
+			#define PDUMPMSVDXREGREAD(args...)
+			#define PDUMPMSVDXPOLEQ(args...)
+			#define PDUMPMSVDXPOL(args...)
+			#define PDUMPBITMAPKM(args...)
+			#define PDUMPDRIVERINFO(args...)
+			#define PDUMPIDLWITHFLAGS(args...)
+			#define PDUMPIDL(args...)
+			#define PDUMPSUSPEND(args...)
+			#define PDUMPRESUME(args...)
+			#define PDUMPMSVDXWRITEREF(args...)
+		#else
+			#error Compiler not specified
+		#endif
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/pdump_osfunc.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/pdump_osfunc.h
new file mode 100644
index 0000000..eb2197f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/pdump_osfunc.h
@@ -0,0 +1,133 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __PDUMP_OSFUNC_H__
+#define __PDUMP_OSFUNC_H__
+
+#include <stdarg.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#define MAX_PDUMP_STRING_LENGTH (256)
+#define PDUMP_GET_SCRIPT_STRING()				\
+	IMG_HANDLE hScript;							\
+	IMG_UINT32	ui32MaxLen;						\
+	PVRSRV_ERROR eError;						\
+	eError = PDumpOSGetScriptString(&hScript, &ui32MaxLen);\
+	if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_MSG_STRING()					\
+	IMG_HANDLE hMsg;							\
+	IMG_UINT32	ui32MaxLen;						\
+	PVRSRV_ERROR eError;						\
+	eError = PDumpOSGetMessageString(&hMsg, &ui32MaxLen);\
+	if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_FILE_STRING()				\
+	IMG_CHAR *pszFileName;					\
+	IMG_UINT32	ui32MaxLen;					\
+	PVRSRV_ERROR eError;					\
+	eError = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLen);\
+	if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_SCRIPT_AND_FILE_STRING()		\
+	IMG_HANDLE hScript;							\
+	IMG_CHAR *pszFileName;						\
+	IMG_UINT32	ui32MaxLenScript;				\
+	IMG_UINT32	ui32MaxLenFileName;				\
+	PVRSRV_ERROR eError;						\
+	eError = PDumpOSGetScriptString(&hScript, &ui32MaxLenScript);\
+	if(eError != PVRSRV_OK) return eError;		\
+	eError = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLenFileName);\
+	if(eError != PVRSRV_OK) return eError;
+
+
+
+	PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript, IMG_UINT32 *pui32MaxLen);
+
+
+	PVRSRV_ERROR PDumpOSGetMessageString(IMG_HANDLE *phMsg, IMG_UINT32 *pui32MaxLen);
+
+
+	PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile, IMG_UINT32 *pui32MaxLen);
+
+
+
+
+#define PDUMP_va_list	va_list
+#define PDUMP_va_start	va_start
+#define PDUMP_va_end	va_end
+
+
+
+IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream);
+
+IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream);
+
+IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID);
+
+IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags);
+
+IMG_BOOL PDumpOSIsSuspended(IMG_VOID);
+
+IMG_BOOL PDumpOSJTInitialised(IMG_VOID);
+
+IMG_BOOL PDumpOSWriteString(IMG_HANDLE hDbgStream,
+		IMG_UINT8 *psui8Data,
+		IMG_UINT32 ui32Size,
+		IMG_UINT32 ui32Flags);
+
+IMG_BOOL PDumpOSWriteString2(IMG_HANDLE	hScript, IMG_UINT32 ui32Flags);
+
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...);
+
+IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...);
+
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...);
+
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszMsg, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs);
+
+IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+
+IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+
+IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
+        IMG_HANDLE hOSMemHandle,
+		IMG_UINT32 ui32Offset,
+		IMG_UINT8 *pui8LinAddr,
+		IMG_UINT32 ui32PageSize,
+		IMG_DEV_PHYADDR *psDevPAddr);
+
+IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
+		IMG_UINT32 ui32Offset,
+		IMG_PUINT8 pui8LinAddr,
+		IMG_UINT32 *pui32PageOffset);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/perproc.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/perproc.h
new file mode 100644
index 0000000..11c1608
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/perproc.h
@@ -0,0 +1,106 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __PERPROC_H__
+#define __PERPROC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_types.h"
+#include "resman.h"
+
+#include "handle.h"
+
+typedef struct _PVRSRV_PER_PROCESS_DATA_
+{
+	IMG_UINT32		ui32PID;
+	IMG_HANDLE		hBlockAlloc;
+	PRESMAN_CONTEXT 	hResManContext;
+	IMG_HANDLE		hPerProcData;
+	PVRSRV_HANDLE_BASE 	*psHandleBase;
+#if defined (PVR_SECURE_HANDLES)
+
+	IMG_BOOL		bHandlesBatched;
+#endif
+	IMG_UINT32		ui32RefCount;
+
+
+	IMG_BOOL		bInitProcess;
+
+
+	IMG_HANDLE		hOsPrivateData;
+} PVRSRV_PER_PROCESS_DATA;
+
+PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID);
+
+PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32	ui32PID);
+IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32	ui32PID);
+
+PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID);
+PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID);
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindPerProcessData)
+#endif
+static INLINE
+PVRSRV_PER_PROCESS_DATA *PVRSRVFindPerProcessData(IMG_VOID)
+{
+	return PVRSRVPerProcessData(OSGetCurrentProcessIDKM());
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVProcessPrivateData(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	return (psPerProc != IMG_NULL) ? psPerProc->hOsPrivateData : IMG_NULL;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPerProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVPerProcessPrivateData(IMG_UINT32 ui32PID)
+{
+	return PVRSRVProcessPrivateData(PVRSRVPerProcessData(ui32PID));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindPerProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVFindPerProcessPrivateData(IMG_VOID)
+{
+	return PVRSRVProcessPrivateData(PVRSRVFindPerProcessData());
+}
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/power.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/power.h
new file mode 100644
index 0000000..1e47736
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/power.h
@@ -0,0 +1,116 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef POWER_H
+#define POWER_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+
+typedef struct _PVRSRV_POWER_DEV_TAG_
+{
+	PFN_PRE_POWER					pfnPrePower;
+	PFN_POST_POWER					pfnPostPower;
+	PFN_PRE_CLOCKSPEED_CHANGE		pfnPreClockSpeedChange;
+	PFN_POST_CLOCKSPEED_CHANGE		pfnPostClockSpeedChange;
+	IMG_HANDLE						hDevCookie;
+	IMG_UINT32						ui32DeviceIndex;
+	PVRSRV_DEV_POWER_STATE 			eDefaultPowerState;
+	PVRSRV_DEV_POWER_STATE 			eCurrentPowerState;
+	struct _PVRSRV_POWER_DEV_TAG_	*psNext;
+	struct _PVRSRV_POWER_DEV_TAG_	**ppsThis;
+
+} PVRSRV_POWER_DEV;
+
+typedef enum _PVRSRV_INIT_SERVER_STATE_
+{
+	PVRSRV_INIT_SERVER_Unspecified		= -1,
+	PVRSRV_INIT_SERVER_RUNNING			= 0,
+	PVRSRV_INIT_SERVER_RAN				= 1,
+	PVRSRV_INIT_SERVER_SUCCESSFUL		= 2,
+	PVRSRV_INIT_SERVER_NUM				= 3,
+	PVRSRV_INIT_SERVER_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_INIT_SERVER_STATE, *PPVRSRV_INIT_SERVER_STATE;
+
+IMG_IMPORT
+IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE	eInitServerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE	eInitServerState, IMG_BOOL bState);
+
+
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32	ui32CallerID,
+							 IMG_BOOL	bSystemPowerEvent);
+IMG_IMPORT
+IMG_VOID PVRSRVPowerUnlock(IMG_UINT32	ui32CallerID);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32				ui32DeviceIndex,
+										 PVRSRV_DEV_POWER_STATE	eNewPowerState,
+										 IMG_UINT32				ui32CallerID,
+										 IMG_BOOL				bRetainMutex);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewPowerState);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewPowerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetPowerStateKM (PVRSRV_SYS_POWER_STATE ePVRState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32					ui32DeviceIndex,
+									   PFN_PRE_POWER				pfnPrePower,
+									   PFN_POST_POWER				pfnPostPower,
+									   PFN_PRE_CLOCKSPEED_CHANGE	pfnPreClockSpeedChange,
+									   PFN_POST_CLOCKSPEED_CHANGE	pfnPostClockSpeedChange,
+									   IMG_HANDLE					hDevCookie,
+									   PVRSRV_DEV_POWER_STATE		eCurrentPowerState,
+									   PVRSRV_DEV_POWER_STATE		eDefaultPowerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex);
+
+IMG_IMPORT
+IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32	ui32DeviceIndex,
+											 IMG_BOOL	bIdleDevice,
+											 IMG_VOID	*pvInfo);
+
+IMG_IMPORT
+IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32	ui32DeviceIndex,
+										  IMG_BOOL		bIdleDevice,
+										  IMG_VOID		*pvInfo);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/queue.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/queue.h
new file mode 100644
index 0000000..f3e5df6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/queue.h
@@ -0,0 +1,115 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef QUEUE_H
+#define QUEUE_H
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define UPDATE_QUEUE_ROFF(psQueue, ui32Size)						\
+	psQueue->ui32ReadOffset = (psQueue->ui32ReadOffset + ui32Size)	\
+	& (psQueue->ui32QueueSize - 1);
+
+ typedef struct _COMMAND_COMPLETE_DATA_
+ {
+	IMG_BOOL			bInUse;
+
+	IMG_UINT32			ui32DstSyncCount;
+	IMG_UINT32			ui32SrcSyncCount;
+	PVRSRV_SYNC_OBJECT	*psDstSync;
+	PVRSRV_SYNC_OBJECT	*psSrcSync;
+	IMG_UINT32			ui32AllocSize;
+ }COMMAND_COMPLETE_DATA, *PCOMMAND_COMPLETE_DATA;
+
+#if !defined(USE_CODE)
+IMG_VOID QueueDumpDebugInfo(IMG_VOID);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVProcessQueues (IMG_UINT32	ui32CallerID,
+								  IMG_BOOL		bFlush);
+
+#if defined(__linux__) && defined(__KERNEL__)
+#include <linux/types.h>
+#include <linux/seq_file.h>
+off_t
+QueuePrintQueues (IMG_CHAR * buffer, size_t size, off_t off);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off);
+void ProcSeqShowQueue(struct seq_file *sfile,void* el);
+#endif
+
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
+													 PVRSRV_QUEUE_INFO **ppsQueueInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO	*psQueue,
+												PVRSRV_COMMAND		**ppsCommand,
+												IMG_UINT32			ui32DevIndex,
+												IMG_UINT16			CommandType,
+												IMG_UINT32			ui32DstSyncCount,
+												PVRSRV_KERNEL_SYNC_INFO	*apsDstSync[],
+												IMG_UINT32			ui32SrcSyncCount,
+												PVRSRV_KERNEL_SYNC_INFO	*apsSrcSync[],
+												IMG_SIZE_T			ui32DataByteSize );
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
+												IMG_SIZE_T ui32ParamSize,
+												IMG_VOID **ppvSpace);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+												PVRSRV_COMMAND *psCommand);
+
+IMG_IMPORT
+IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie, IMG_BOOL bScheduleMISR);
+
+IMG_VOID PVRSRVCommandCompleteCallbacks(IMG_VOID);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32		ui32DevIndex,
+										 PFN_CMD_PROC	*ppfnCmdProcList,
+										 IMG_UINT32		ui32MaxSyncsPerCmd[][2],
+										 IMG_UINT32		ui32CmdCount);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32	ui32DevIndex,
+									   IMG_UINT32	ui32CmdCount);
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/ra.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/ra.h
new file mode 100644
index 0000000..d537601
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/ra.h
@@ -0,0 +1,151 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _RA_H_
+#define _RA_H_
+
+#include "img_types.h"
+#include "hash.h"
+#include "osfunc.h"
+
+typedef struct _RA_ARENA_ RA_ARENA;
+typedef struct _BM_MAPPING_ BM_MAPPING;
+
+
+
+#define RA_STATS
+
+
+struct _RA_STATISTICS_
+{
+
+    IMG_SIZE_T uSpanCount;
+
+
+    IMG_SIZE_T uLiveSegmentCount;
+
+
+    IMG_SIZE_T uFreeSegmentCount;
+
+
+    IMG_SIZE_T uTotalResourceCount;
+
+
+    IMG_SIZE_T uFreeResourceCount;
+
+
+    IMG_SIZE_T uCumulativeAllocs;
+
+
+    IMG_SIZE_T uCumulativeFrees;
+
+
+    IMG_SIZE_T uImportCount;
+
+
+    IMG_SIZE_T uExportCount;
+};
+typedef struct _RA_STATISTICS_ RA_STATISTICS;
+
+struct _RA_SEGMENT_DETAILS_
+{
+	IMG_SIZE_T      uiSize;
+	IMG_CPU_PHYADDR sCpuPhyAddr;
+	IMG_HANDLE      hSegment;
+};
+typedef struct _RA_SEGMENT_DETAILS_ RA_SEGMENT_DETAILS;
+
+RA_ARENA *
+RA_Create (IMG_CHAR *name,
+           IMG_UINTPTR_T base,
+           IMG_SIZE_T uSize,
+           BM_MAPPING *psMapping,
+           IMG_SIZE_T uQuantum,
+           IMG_BOOL (*imp_alloc)(IMG_VOID *_h,
+                                IMG_SIZE_T uSize,
+                                IMG_SIZE_T *pActualSize,
+                                BM_MAPPING **ppsMapping,
+                                IMG_UINT32 uFlags,
+                                IMG_UINTPTR_T *pBase),
+           IMG_VOID (*imp_free) (IMG_VOID *,
+                                IMG_UINTPTR_T,
+                                BM_MAPPING *),
+           IMG_VOID (*backingstore_free) (IMG_VOID *,
+                                          IMG_SIZE_T,
+                                          IMG_SIZE_T,
+                                          IMG_HANDLE),
+           IMG_VOID *import_handle);
+
+IMG_VOID
+RA_Delete (RA_ARENA *pArena);
+
+IMG_BOOL
+RA_TestDelete (RA_ARENA *pArena);
+
+IMG_BOOL
+RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize);
+
+IMG_BOOL
+RA_Alloc (RA_ARENA *pArena,
+          IMG_SIZE_T uSize,
+          IMG_SIZE_T *pActualSize,
+          BM_MAPPING **ppsMapping,
+          IMG_UINT32 uFlags,
+          IMG_UINT32 uAlignment,
+		  IMG_UINT32 uAlignmentOffset,
+          IMG_UINTPTR_T *pBase);
+
+IMG_VOID
+RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore);
+
+
+#ifdef RA_STATS
+
+#define CHECK_SPACE(total)					\
+{											\
+	if(total<100) 							\
+		return PVRSRV_ERROR_INVALID_PARAMS;	\
+}
+
+#define UPDATE_SPACE(str, count, total)		\
+{											\
+	if(count == -1)					 		\
+		return PVRSRV_ERROR_INVALID_PARAMS;	\
+	else									\
+	{										\
+		str += count;						\
+		total -= count;						\
+	}										\
+}
+
+
+IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails);
+
+
+PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
+							IMG_CHAR **ppszStr,
+							IMG_UINT32 *pui32StrLen);
+
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/resman.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/resman.h
new file mode 100644
index 0000000..a2c6d02
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/resman.h
@@ -0,0 +1,109 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef __RESMAN_H__
+#define __RESMAN_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+enum {
+
+	RESMAN_TYPE_SHARED_PB_DESC = 1,
+	RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
+	RESMAN_TYPE_HW_RENDER_CONTEXT,
+	RESMAN_TYPE_HW_TRANSFER_CONTEXT,
+	RESMAN_TYPE_HW_2D_CONTEXT,
+	RESMAN_TYPE_TRANSFER_CONTEXT,
+
+
+
+
+
+	RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
+	RESMAN_TYPE_DISPLAYCLASS_DEVICE,
+
+
+	RESMAN_TYPE_BUFFERCLASS_DEVICE,
+
+
+	RESMAN_TYPE_OS_USERMODE_MAPPING,
+
+
+	RESMAN_TYPE_DEVICEMEM_CONTEXT,
+	RESMAN_TYPE_DEVICECLASSMEM_MAPPING,
+	RESMAN_TYPE_DEVICEMEM_MAPPING,
+	RESMAN_TYPE_DEVICEMEM_WRAP,
+	RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+	RESMAN_TYPE_EVENT_OBJECT,
+    RESMAN_TYPE_SHARED_MEM_INFO,
+    RESMAN_TYPE_MODIFY_SYNC_OPS,
+
+
+	RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION
+};
+
+#define RESMAN_CRITERIA_ALL				0x00000000
+#define RESMAN_CRITERIA_RESTYPE			0x00000001
+#define RESMAN_CRITERIA_PVOID_PARAM		0x00000002
+#define RESMAN_CRITERIA_UI32_PARAM		0x00000004
+
+typedef PVRSRV_ERROR (*RESMAN_FREE_FN)(IMG_PVOID pvParam, IMG_UINT32 ui32Param);
+
+typedef struct _RESMAN_ITEM_ *PRESMAN_ITEM;
+typedef struct _RESMAN_CONTEXT_ *PRESMAN_CONTEXT;
+
+PVRSRV_ERROR ResManInit(IMG_VOID);
+IMG_VOID ResManDeInit(IMG_VOID);
+
+PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT	hResManContext,
+							   IMG_UINT32		ui32ResType,
+							   IMG_PVOID		pvParam,
+							   IMG_UINT32		ui32Param,
+							   RESMAN_FREE_FN	pfnFreeResource);
+
+PVRSRV_ERROR ResManFreeResByPtr(PRESMAN_ITEM	psResItem);
+
+PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT	hResManContext,
+									 IMG_UINT32			ui32SearchCriteria,
+									 IMG_UINT32			ui32ResType,
+									 IMG_PVOID			pvParam,
+									 IMG_UINT32			ui32Param);
+
+PVRSRV_ERROR ResManDissociateRes(PRESMAN_ITEM		psResItem,
+							 PRESMAN_CONTEXT	psNewResManContext);
+
+PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT	hResManContext,
+									 PRESMAN_ITEM		psItem);
+
+PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE			hPerProc,
+								 PRESMAN_CONTEXT	*phResManContext);
+IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT hResManContext,
+								IMG_BOOL		bKernelContext);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/services_headers.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/services_headers.h
new file mode 100644
index 0000000..4f6c2a2
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/services_headers.h
@@ -0,0 +1,45 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef SERVICES_HEADERS_H
+#define SERVICES_HEADERS_H
+
+#ifdef DEBUG_RELEASE_BUILD
+#pragma optimize( "", off )
+#define DEBUG		1
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "power.h"
+#include "resman.h"
+#include "queue.h"
+#include "srvkm.h"
+#include "kerneldisplay.h"
+#include "sysconfig.h"
+#include "pvr_debug.h"
+#include "metrics.h"
+#include "osfunc.h"
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/srvkm.h b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/srvkm.h
new file mode 100644
index 0000000..5506992
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/srvkm/include/srvkm.h
@@ -0,0 +1,65 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef SRVKM_H
+#define SRVKM_H
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+	#ifdef PVR_DISABLE_LOGGING
+	#define PVR_LOG(X)
+	#else
+	#define PVR_LOG(X)			PVRSRVReleasePrintf X
+	#endif
+
+	IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVReleasePrintf(const IMG_CHAR *pszFormat,
+										...);
+
+	IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32	ui32PID);
+	IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32	ui32PID);
+
+	IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State);
+
+	PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer, IMG_SIZE_T *puiBufSize, IMG_BOOL bSave);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#define LOOP_UNTIL_TIMEOUT(TIMEOUT) \
+{\
+	IMG_UINT32 uiOffset, uiStart, uiCurrent, uiNotLastLoop;								\
+	for(uiOffset = 0, uiStart = OSClockus(), uiCurrent = uiStart + 1, uiNotLastLoop = 1;\
+		((uiCurrent - uiStart + uiOffset) < TIMEOUT) || uiNotLastLoop--;				\
+		uiCurrent = OSClockus(),														\
+		uiOffset = uiCurrent < uiStart ? IMG_UINT32_MAX - uiStart : uiOffset,			\
+		uiStart = uiCurrent < uiStart ? 0 : uiStart)
+
+#define END_LOOP_UNTIL_TIMEOUT() \
+}
+
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/common/sysconfig.c b/drivers/gpu/drm/emgd/pvr/services4/system/common/sysconfig.c
new file mode 100644
index 0000000..6146806
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/common/sysconfig.c
@@ -0,0 +1,1367 @@
+/* -*- syscommon-c -*-
+ *-----------------------------------------------------------------------------
+ * Filename: syscommon.c
+ * $Revision: 1.11 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description: platform detection, and sharing of correct platform interface.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#include <linux/pci.h>
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "kerneldisplay.h"
+#include "oemfuncs.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#ifdef SUPPORT_MSVDX
+#include "msvdx_defs.h"
+#include "msvdxapi.h"
+#include "msvdx_infokm.h"
+#include "osfunc.h"
+#endif
+#include "pdump_km.h"
+#include "syslocal.h"
+#include "sysconfig.h"
+#include "pvr_debug.h"
+#include "msvdx_pvr.h"
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Pointer to "System Data" used by all platform blocks, exported
+* in "syscommon.h" header file.
+*/
+/* --------------------------------------------------------------------------*/
+SYS_DATA *gpsSysData = (SYS_DATA*)IMG_NULL;
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Pointer to found platform interface. It is IMG_NULL when no
+* correct platform can be found.
+*/
+/* --------------------------------------------------------------------------*/
+SYS_PLATFORM_INTERFACE *gpsSysPlatformInterface = (SYS_PLATFORM_INTERFACE*)IMG_NULL;
+
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Poulsbo platform interface.
+*/
+/* --------------------------------------------------------------------------*/
+extern SYS_PLATFORM_INTERFACE gpsSysPlatformInterfacePlb;
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Atom E6xx platform interface.
+*/
+/* --------------------------------------------------------------------------*/
+extern SYS_PLATFORM_INTERFACE gpsSysPlatformInterfaceTnc;
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Table to available platforms interfaces.
+* The last element must be set to IMG_NULL.
+*
+* @Param &gpsSysPlatformInterfacePlb Poulsbo interface
+* @Param &gpsSysPlatformInterfaceTnc Atom E6xx interface
+*/
+/* --------------------------------------------------------------------------*/
+SYS_PLATFORM_INTERFACE* gpsSysPlatformInterfacesTab[] = {	&gpsSysPlatformInterfacePlb,
+								&gpsSysPlatformInterfaceTnc,
+								(SYS_PLATFORM_INTERFACE*)IMG_NULL};
+
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Function to detect platform and set "gpsSysPlatformInterface" to
+* one member of "gpsSysPlatformInterfacesTab".
+*
+* @Param IMG_VOID
+*
+* @Returns
+*/
+/* --------------------------------------------------------------------------*/
+IMG_VOID SysPlatformDetect(IMG_VOID)
+{
+	SYS_PLATFORM_INTERFACE** psSysPlatformInterfacesTab = gpsSysPlatformInterfacesTab;
+
+	while(*psSysPlatformInterfacesTab != IMG_NULL) {
+
+		if(pci_get_device(SYS_SGX_DEV_VENDOR_ID, (unsigned short)((*psSysPlatformInterfacesTab)->uiSgxDevDeviceID), NULL)) {
+			gpsSysPlatformInterface = *psSysPlatformInterfacesTab;
+			PVR_DPF((PVR_DBG_MESSAGE,"Platform detected: %s", gpsSysPlatformInterface->sProductName));
+			return;
+		}
+		PVR_DPF((PVR_DBG_MESSAGE,"Platform search: %s", (*psSysPlatformInterfacesTab)->sProductName));
+		psSysPlatformInterfacesTab++;
+	}
+	PVR_DPF((PVR_DBG_ERROR,"Platform detected Failed"));
+}
+
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis  Interface for Atom E6xx device
+*/
+/* ----------------------------------------------------------------------------*/
+
+static SYS_DATA  gsSysData;
+
+static SYS_SPECIFIC_DATA gsSysSpecificData;
+
+static IMG_UINT32		gui32SGXDeviceID;
+static SGX_DEVICE_MAP	gsSGXDeviceMap;
+static IMG_UINT32		gui32MSVDXDeviceID;
+
+#ifdef SUPPORT_MSVDX
+static IMG_UINT32		gui32MSVDXDeviceID;
+static MSVDX_DEVICE_MAP	gsMSVDXDeviceMap;
+#endif
+
+
+#if defined(NO_HARDWARE)
+static IMG_CPU_VIRTADDR gsSGXRegsCPUVAddr;
+#ifdef SUPPORT_MSVDX
+static IMG_CPU_VIRTADDR gsMSVDXRegsCPUVAddr;
+#endif
+#endif
+
+#if !defined(NO_HARDWARE)
+static IMG_CPU_VIRTADDR gsPoulsboRegsCPUVaddr;
+
+#if defined(MAP_UNUSED_MAPPINGS)
+static IMG_CPU_VIRTADDR gsPoulsboDisplayRegsCPUVaddr;
+#endif
+
+#endif
+
+#ifdef	LDM_PCI
+extern struct pci_dev *gpsPVRLDMDev;
+#endif
+
+IMG_UINT32 PVRSRV_BridgeDispatchKM( IMG_UINT32  Ioctl,
+									IMG_BYTE   *pInBuf,
+									IMG_UINT32  InBufLen,
+									IMG_BYTE   *pOutBuf,
+									IMG_UINT32  OutBufLen,
+									IMG_UINT32 *pdwBytesTransferred);
+
+#ifdef __linux__
+#define	ADDR_RANGE_INDEX	(MMADR_INDEX - 4)
+#if defined(SGX_FEATURE_HOST_PORT)
+#define	HP_ADDR_RANGE_INDEX	(GMADR_INDEX - 4)
+#endif
+static PVRSRV_ERROR PCIInitDev(SYS_DATA *psSysData)
+{
+	SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+#ifdef	LDM_PCI
+	psSysSpecData->hSGXPCI = OSPCISetDev((IMG_VOID *)psSysSpecData->psPCIDev, HOST_PCI_INIT_FLAG_BUS_MASTER);
+#else
+	psSysSpecData->hSGXPCI = OSPCIAcquireDev(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID, HOST_PCI_INIT_FLAG_BUS_MASTER);
+#endif
+	if (!psSysSpecData->hSGXPCI)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Failed to acquire PCI device"));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	 SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_PCI_ACQUIRE_DEV);
+
+	PVR_TRACE(("PCI memory region: %x to %x", OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, ADDR_RANGE_INDEX), OSPCIAddrRangeEnd(psSysSpecData->hSGXPCI, ADDR_RANGE_INDEX)));
+#if defined(SGX_FEATURE_HOST_PORT)
+	PVR_TRACE(("Host Port region: %x to %x", OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, HP_ADDR_RANGE_INDEX), OSPCIAddrRangeEnd(psSysSpecData->hSGXPCI, HP_ADDR_RANGE_INDEX)));
+#endif
+
+	if (OSPCIAddrRangeLen(psSysSpecData->hSGXPCI, ADDR_RANGE_INDEX) < MAX_OFFSET)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Device memory region isn't big enough"));
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+
+	if (OSPCIRequestAddrRange(psSysSpecData->hSGXPCI, ADDR_RANGE_INDEX) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Device memory region not available"));
+		return PVRSRV_ERROR_GENERIC;
+	}
+	 SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_PCI_REQUEST_SGX_ADDR_RANGE);
+
+
+#if defined(SGX_FEATURE_HOST_PORT)
+	if (OSPCIRequestAddrRange(psSysSpecData->hSGXPCI, HP_ADDR_RANGE_INDEX) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Host Port region not available"));
+		return PVRSRV_ERROR_GENERIC;
+	}
+	 SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_PCI_REQUEST_HOST_PORT_RANGE);
+#endif
+	return PVRSRV_OK;
+}
+
+static IMG_VOID PCIDeInitDev(SYS_DATA *psSysData)
+{
+	SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+	if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_PCI_REQUEST_SGX_ADDR_RANGE))
+	{
+		OSPCIReleaseAddrRange(psSysSpecData->hSGXPCI, ADDR_RANGE_INDEX);
+	}
+
+#if defined(SGX_FEATURE_HOST_PORT)
+	if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_PCI_REQUEST_HOST_PORT_RANGE))
+	{
+		OSPCIReleaseAddrRange(psSysSpecData->hSGXPCI, HP_ADDR_RANGE_INDEX);
+	}
+#endif
+
+	if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_PCI_ACQUIRE_DEV))
+	{
+		OSPCIReleaseDev(psSysSpecData->hSGXPCI);
+	}
+}
+#else
+static PVRSRV_ERROR FindPCIDevice(IMG_UINT16 ui16VenID, IMG_UINT16 ui16DevID, PCICONFIG_SPACE *psPCISpace)
+{
+	IMG_UINT32 ui32BusNum;
+	IMG_UINT32 ui32DevNum;
+	IMG_UINT32 ui32VenDevID;
+
+
+	for (ui32BusNum=0; ui32BusNum < 255; ui32BusNum++)
+	{
+
+		for (ui32DevNum=0; ui32DevNum < 32; ui32DevNum++)
+		{
+
+			ui32VenDevID=OSPCIReadDword(ui32BusNum, ui32DevNum, 0, 0);
+
+
+			if (ui32VenDevID == (IMG_UINT32)((ui16DevID<<16)+ui16VenID))
+			{
+				IMG_UINT32 ui32Idx;
+
+
+				OSPCIWriteDword(ui32BusNum, ui32DevNum, 0, 4, OSPCIReadDword(ui32BusNum, ui32DevNum, 0, 4) | 0x02);
+
+
+				for (ui32Idx=0; ui32Idx < 64; ui32Idx++)
+				{
+					psPCISpace->u.aui32PCISpace[ui32Idx] = OSPCIReadDword(ui32BusNum, ui32DevNum, 0, ui32Idx*4);
+
+					if (ui32Idx < 16)
+					{
+						PVR_DPF((PVR_DBG_VERBOSE,"%08X\n",psPCISpace->u.aui32PCISpace[ui32Idx]));
+					}
+				}
+				return PVRSRV_OK;
+			}
+
+		}
+
+	}
+
+	PVR_DPF((PVR_DBG_ERROR,"Couldn't find PCI device"));
+
+	return PVRSRV_ERROR_GENERIC;
+}
+#endif
+
+static PVRSRV_ERROR SysLocateDevices(SYS_DATA *psSysData)
+{
+#if !defined(NO_HARDWARE) || defined(__linux__)
+	IMG_UINT32 ui32BaseAddr;
+	IMG_UINT32 ui32IRQ;
+#endif
+#if defined(SGX_FEATURE_HOST_PORT)
+	IMG_UINT32 ui32HostPortAddr = 0UL;
+#endif
+#if defined(NO_HARDWARE)
+	IMG_CPU_PHYADDR sCpuPAddr;
+#endif
+#if defined(NO_HARDWARE) || defined(__linux__)
+	SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+#endif
+#if (!defined(__linux__) || defined(NO_HARDWARE))
+	PVRSRV_ERROR eError;
+#endif
+
+#ifdef __linux__
+	ui32BaseAddr = OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, ADDR_RANGE_INDEX);
+#if defined(SGX_FEATURE_HOST_PORT)
+	ui32HostPortAddr = OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, HP_ADDR_RANGE_INDEX);
+#endif
+	if (OSPCIIRQ(psSysSpecData->hSGXPCI, &ui32IRQ) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysLocateDevices: Couldn't get IRQ"));
+		return PVRSRV_ERROR_INVALID_DEVICE;
+	}
+	PVR_TRACE(("IRQ: %d", ui32IRQ));
+#else
+	PVRSRV_ERROR eError;
+	PCICONFIG_SPACE	sPCISpace;
+
+	eError = FindPCIDevice(VENDOR_ID, DEVICE_ID, &sPCISpace);
+	if (eError == PVRSRV_OK)
+	{
+		ui32BaseAddr = sPCISpace.u.aui32PCISpace[MMADR_INDEX];
+#if defined(SGX_FEATURE_HOST_PORT)
+		ui32HostPortAddr = sPCISpace.u.aui32PCISpace[GMADR_INDEX];
+#endif
+	}
+	else
+	{
+		return PVRSRV_ERROR_INVALID_DEVICE;
+	}
+
+	ui32IRQ = (IMG_UINT32)sPCISpace.u.aui8PCISpace[0x3C];
+#endif
+
+
+	gsSGXDeviceMap.ui32Flags = 0x0;
+
+
+#if defined(NO_HARDWARE)
+
+	gsSGXDeviceMap.ui32IRQ = 0;
+#else
+	gsSGXDeviceMap.ui32IRQ = ui32IRQ;
+#endif
+
+#if defined(NO_HARDWARE)
+
+	eError = OSBaseAllocContigMemory(SGX_REG_SIZE,
+										&gsSGXRegsCPUVAddr,
+										&sCpuPAddr);
+	if(eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+	SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_ALLOC_DUMMY_SGX_REGS);
+
+	gsSGXDeviceMap.sRegsCpuPBase = sCpuPAddr;
+
+	OSMemSet(gsSGXRegsCPUVAddr, 0, SGX_REG_SIZE);
+
+#if defined(__linux__)
+
+	gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr;
+#else
+
+	gsSGXDeviceMap.pvRegsCpuVBase = IMG_NULL;
+#endif
+
+#else
+	gsSGXDeviceMap.sRegsSysPBase.uiAddr = ui32BaseAddr + SGX_REGS_OFFSET;
+#endif
+
+
+	gsSGXDeviceMap.sRegsCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase);
+	gsSGXDeviceMap.ui32RegsSize = SGX_REG_SIZE;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+
+	gsSGXDeviceMap.ui32Flags = SGX_HOSTPORT_PRESENT;
+	gsSGXDeviceMap.sHPSysPBase.uiAddr = ui32HostPortAddr;
+	gsSGXDeviceMap.sHPCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sHPSysPBase);
+	gsSGXDeviceMap.ui32HPSize = SYS_SGX_HP_SIZE;
+#endif
+
+
+
+
+	gsSGXDeviceMap.sLocalMemSysPBase.uiAddr = 0;
+	gsSGXDeviceMap.sLocalMemDevPBase.uiAddr = 0;
+	gsSGXDeviceMap.sLocalMemCpuPBase.uiAddr = 0;
+	gsSGXDeviceMap.ui32LocalMemSize = 0;
+
+#if !defined(NO_HARDWARE)
+
+	{
+		IMG_SYS_PHYADDR sPoulsboRegsCpuPBase;
+
+		sPoulsboRegsCpuPBase.uiAddr = ui32BaseAddr + REGS_OFFSET;
+		gsPoulsboRegsCPUVaddr = OSMapPhysToLin(SysSysPAddrToCpuPAddr(sPoulsboRegsCpuPBase),
+												 REG_SIZE,
+												 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+												 IMG_NULL);
+
+#if defined(MAP_UNUSED_MAPPINGS)
+		sPoulsboRegsCpuPBase.uiAddr = ui32BaseAddr + DISPLAY_REGS_OFFSET;
+		gsPoulsboDisplayRegsCPUVaddr = OSMapPhysToLin(SysSysPAddrToCpuPAddr(sPoulsboRegsCpuPBase),
+												 DISPLAY_REG_SIZE,
+												 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+												 IMG_NULL);
+#endif
+	}
+#endif
+
+#ifdef SUPPORT_MSVDX
+
+
+#if defined(NO_HARDWARE)
+
+	eError = OSBaseAllocContigMemory(MSVDX_REG_SIZE,
+										&gsMSVDXRegsCPUVAddr,
+										&sCpuPAddr);
+	if(eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+	SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_ALLOC_DUMMY_MSVDX_REGS);
+	gsMSVDXDeviceMap.sRegsCpuPBase = sCpuPAddr;
+
+	OSMemSet(gsMSVDXRegsCPUVAddr, 0, MSVDX_REG_SIZE);
+
+#if defined(__linux__)
+
+	gsMSVDXDeviceMap.pvRegsCpuVBase = gsMSVDXRegsCPUVAddr;
+#else
+
+	gsMSVDXDeviceMap.pvRegsCpuVBase = IMG_NULL;
+#endif
+#else
+	gsMSVDXDeviceMap.sRegsCpuPBase.uiAddr = ui32BaseAddr + MSVDX_REGS_OFFSET;
+#endif
+	gsMSVDXDeviceMap.sRegsSysPBase		  = SysCpuPAddrToSysPAddr(gsMSVDXDeviceMap.sRegsCpuPBase);
+	gsMSVDXDeviceMap.ui32RegsSize		  = MSVDX_REG_SIZE;
+
+
+
+
+
+	gsMSVDXDeviceMap.sLocalMemSysPBase.uiAddr = 0;
+	gsMSVDXDeviceMap.sLocalMemDevPBase.uiAddr = 0;
+	gsMSVDXDeviceMap.sLocalMemCpuPBase.uiAddr = 0;
+	gsMSVDXDeviceMap.ui32LocalMemSize		  = 0;
+
+
+
+	gsMSVDXDeviceMap.ui32IRQ = ui32IRQ;
+
+#endif
+
+
+
+	return PVRSRV_OK;
+}
+
+#ifdef SUPPORT_MSVDX_FPGA
+static PVRSRV_ERROR FindPCIDevice(IMG_UINT16 ui16VenID, IMG_UINT16 ui16DevID, PCICONFIG_SPACE *psPCISpace)
+{
+	IMG_UINT32  ui32BusNum;
+	IMG_UINT32  ui32DevNum;
+	IMG_UINT32  ui32VenDevID;
+	IMG_UINT32	ui32BarIndex;
+
+
+	for (ui32BusNum=0; ui32BusNum < 255; ui32BusNum++)
+	{
+
+		for (ui32DevNum=0; ui32DevNum < 32; ui32DevNum++)
+		{
+
+			ui32VenDevID=OSPCIReadDword(ui32BusNum, ui32DevNum, 0, 0);
+
+
+			if (ui32VenDevID == (IMG_UINT32)((ui16DevID<<16)+ui16VenID))
+			{
+				IMG_UINT32 ui32Idx;
+
+
+				OSPCIWriteDword(ui32BusNum, ui32DevNum, 0, 4, OSPCIReadDword(ui32BusNum, ui32DevNum, 0, 4) | 0x02);
+
+				psPCISpace->ui32BusNum  = ui32BusNum;
+				psPCISpace->ui32DevNum  = ui32DevNum;
+				psPCISpace->ui32FuncNum = 0;
+
+
+				for (ui32Idx=0; ui32Idx < 64; ui32Idx++)
+				{
+					psPCISpace->u.aui32PCISpace[ui32Idx] = OSPCIReadDword(ui32BusNum, ui32DevNum, 0, ui32Idx*4);
+
+					if (ui32Idx < 16)
+					{
+						PVR_DPF((PVR_DBG_VERBOSE,"%08X\n",psPCISpace->u.aui32PCISpace[ui32Idx]));
+					}
+				}
+
+				for (ui32BarIndex = 0; ui32BarIndex < 6; ui32BarIndex++)
+				{
+					GetPCIMemSpaceSize (ui32BusNum, ui32DevNum, ui32BarIndex, &psPCISpace->aui32PCIMemSpaceSize[ui32BarIndex]);
+				}
+				return PVRSRV_OK;
+			}
+
+		}
+
+	}
+
+	PVR_DPF((PVR_DBG_ERROR,"Couldn't find PCI device"));
+
+	return PVRSRV_ERROR_GENERIC;
+}
+
+static IMG_UINT32 GetPCIMemSpaceSize (IMG_UINT32 ui32BusNum, IMG_UINT32 ui32DevNum, IMG_UINT32 ui32BarIndex, IMG_UINT32* pui32PCIMemSpaceSize)
+{
+
+	IMG_UINT32	ui32AddressRange;
+	IMG_UINT32	ui32BarSave;
+
+	ui32BarSave = OSPCIReadDword (ui32BusNum, ui32DevNum, 0, ((4 + ui32BarIndex) * sizeof (IMG_UINT32)));
+
+	OSPCIWriteDword (ui32BusNum, ui32DevNum, 0, ((4 + ui32BarIndex) * sizeof (IMG_UINT32)), 0xFFFFFFFF);
+
+	ui32AddressRange = OSPCIReadDword (ui32BusNum, ui32DevNum, 0, ((4 + ui32BarIndex) * sizeof (IMG_UINT32)));
+
+	OSPCIWriteDword (ui32BusNum, ui32DevNum, 0, ((4 + ui32BarIndex) * sizeof (IMG_UINT32)), ui32BarSave);
+
+	*pui32PCIMemSpaceSize = (~(ui32AddressRange & 0xFFFFFFF0)) + 1;
+	return PVRSRV_OK;
+}
+#endif
+
+
+#ifdef __linux__
+#define VERSION_STR_MAX_LEN_TEMPLATE "SGX revision = 000.000.000"
+static PVRSRV_ERROR SysCreateVersionString(SYS_DATA *psSysData)
+{
+    IMG_UINT32 ui32SGXRevision = 0;
+    IMG_UINT32 ui32MaxStrLen;
+    PVRSRV_ERROR eError;
+    IMG_INT32 i32Count;
+    IMG_CHAR *pszVersionString;
+
+#if !defined(NO_HARDWARE)
+
+    {
+	IMG_VOID *pvSGXRegs;
+
+	pvSGXRegs = OSMapPhysToLin(gsSGXDeviceMap.sRegsCpuPBase,
+											 gsSGXDeviceMap.ui32RegsSize,
+											 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+											 IMG_NULL);
+
+	if (pvSGXRegs != IMG_NULL)
+	{
+            ui32SGXRevision = OSReadHWReg(pvSGXRegs, EUR_CR_CORE_REVISION);
+
+	     OSUnMapPhysToLin(pvSGXRegs,
+		   									 	gsSGXDeviceMap.ui32RegsSize,
+											 	PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+												IMG_NULL);
+	}
+	else
+	{
+	     PVR_DPF((PVR_DBG_ERROR,"SysCreateVersionString: Couldn't map SGX registers"));
+	}
+    }
+#endif
+
+    ui32MaxStrLen = OSStringLength(VERSION_STR_MAX_LEN_TEMPLATE);
+    eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+                          ui32MaxStrLen + 1,
+                          (IMG_PVOID *)&pszVersionString,
+                          IMG_NULL,
+						  "Version String");
+    if(eError != PVRSRV_OK)
+    {
+		return PVRSRV_ERROR_GENERIC;
+    }
+
+    i32Count = OSSNPrintf(pszVersionString, ui32MaxStrLen + 1,
+                           "SGX revision = %u.%u.%u",
+                           (IMG_UINT)((ui32SGXRevision & EUR_CR_CORE_REVISION_MAJOR_MASK)
+                            >> EUR_CR_CORE_REVISION_MAJOR_SHIFT),
+                           (IMG_UINT)((ui32SGXRevision & EUR_CR_CORE_REVISION_MINOR_MASK)
+                            >> EUR_CR_CORE_REVISION_MINOR_SHIFT),
+                           (IMG_UINT)((ui32SGXRevision & EUR_CR_CORE_REVISION_MAINTENANCE_MASK)
+                            >> EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT)
+                           );
+    if(i32Count == -1)
+    {
+        ui32MaxStrLen = OSStringLength(VERSION_STR_MAX_LEN_TEMPLATE);
+        OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                    ui32MaxStrLen + 1,
+                    pszVersionString,
+                    IMG_NULL);
+
+		return PVRSRV_ERROR_GENERIC;
+    }
+
+    psSysData->pszVersionString = pszVersionString;
+
+    return PVRSRV_OK;
+}
+
+static IMG_VOID SysFreeVersionString(SYS_DATA *psSysData)
+{
+    if(psSysData->pszVersionString)
+    {
+        IMG_UINT32 ui32MaxStrLen;
+        ui32MaxStrLen = OSStringLength(VERSION_STR_MAX_LEN_TEMPLATE);
+        OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                    ui32MaxStrLen+1,
+                    psSysData->pszVersionString,
+                    IMG_NULL);
+		psSysData->pszVersionString = NULL;
+    }
+}
+#endif
+PVRSRV_ERROR SysInitialise(IMG_VOID)
+{
+	IMG_UINT32			i;
+	PVRSRV_ERROR 		eError;
+	PVRSRV_DEVICE_NODE	*psDeviceNode;
+	SGX_TIMING_INFORMATION*	psTimingInfo;
+
+	PVR_DPF((PVR_DBG_MESSAGE,"SysInitialise"));
+
+	SysPlatformDetect();
+
+	gpsSysData = &gsSysData;
+	OSMemSet(gpsSysData, 0, sizeof(SYS_DATA));
+
+	gpsSysData->pvSysSpecificData = &gsSysSpecificData;
+	gsSysSpecificData.ui32SysSpecificData = 0;
+#ifdef	LDM_PCI
+
+	PVR_ASSERT(gpsPVRLDMDev != IMG_NULL);
+	gsSysSpecificData.psPCIDev = gpsPVRLDMDev;
+#endif
+
+	eError = OSInitEnvData(&gpsSysData->pvEnvSpecificData);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to setup env structure"));
+		SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+
+
+	psTimingInfo = &gsSGXDeviceMap.sTimingInfo;
+	psTimingInfo->ui32CoreClockSpeed = SYS_SGX_CLOCK_SPEED;
+	psTimingInfo->ui32HWRecoveryFreq = SYS_SGX_HWRECOVERY_TIMEOUT_FREQ;
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+	psTimingInfo->bEnableActivePM = IMG_TRUE;
+#else
+	psTimingInfo->bEnableActivePM = IMG_FALSE;
+#endif
+	psTimingInfo->ui32ActivePowManLatencyms = SYS_SGX_ACTIVE_POWER_LATENCY_MS;
+	psTimingInfo->ui32uKernelFreq = SYS_SGX_PDS_TIMER_FREQ;
+
+#ifdef __linux__
+	eError = PCIInitDev(gpsSysData);
+	if (eError != PVRSRV_OK)
+	{
+		SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+#endif
+
+	gpsSysData->ui32NumDevices = SYS_DEVICE_COUNT;
+
+
+	for(i=0; i<SYS_DEVICE_COUNT; i++)
+	{
+		gpsSysData->sDeviceID[i].uiID = i;
+		gpsSysData->sDeviceID[i].bInUse = IMG_FALSE;
+	}
+
+	gpsSysData->psDeviceNodeList = IMG_NULL;
+	gpsSysData->psQueueList = IMG_NULL;
+
+	eError = SysInitialiseCommon(gpsSysData);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed in SysInitialiseCommon"));
+		SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+
+
+	eError = SysLocateDevices(gpsSysData);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to locate devices"));
+		SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+
+
+	eError = PVRSRVRegisterDevice(gpsSysData, SGXRegisterDevice,
+								  DEVICE_SGX_INTERRUPT, &gui32SGXDeviceID);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register device!"));
+		SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+
+//#ifdef SUPPORT_MSVDX
+	eError = PVRSRVRegisterDevice(gpsSysData, MSVDXRegisterDevice,
+								  DEVICE_MSVDX_INTERRUPT, &gui32MSVDXDeviceID);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register device!"));
+		SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+//#endif
+
+
+	psDeviceNode = gpsSysData->psDeviceNodeList;
+
+	while(psDeviceNode)
+	{
+
+		switch(psDeviceNode->sDevId.eDeviceType)
+		{
+			case PVRSRV_DEVICE_TYPE_SGX:
+			{
+				DEVICE_MEMORY_INFO *psDevMemoryInfo;
+				DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+
+				psDeviceNode->psLocalDevMemArena = IMG_NULL;
+
+
+				psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+				psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+
+				for(i=0; i<psDevMemoryInfo->ui32HeapCount; i++)
+				{
+					psDeviceMemoryHeap[i].ui32Attribs |= PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG;
+#ifdef OEM_CUSTOMISE
+
+#endif
+				}
+
+				break;
+			}
+
+//#ifdef SUPPORT_MSVDX
+			case PVRSRV_DEVICE_TYPE_MSVDX:
+			{
+				DEVICE_MEMORY_INFO *psDevMemoryInfo;
+				DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+
+				psDeviceNode->psLocalDevMemArena = IMG_NULL;
+
+
+				psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+				psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+
+				for(i=0; i<psDevMemoryInfo->ui32HeapCount; i++)
+				{
+					psDeviceMemoryHeap[i].ui32Attribs |= PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG;
+#ifdef OEM_CUSTOMISE
+
+#endif
+				}
+				break;
+			}
+//#endif
+			default:
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to find SGX device node!"));
+				return PVRSRV_ERROR_INIT_FAILURE;
+			}
+		}
+
+
+		psDeviceNode = psDeviceNode->psNext;
+	}
+
+	PDUMPINIT();
+	SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_PDUMP_INIT);
+
+
+	eError = PVRSRVInitialiseDevice (gui32SGXDeviceID);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialise device!"));
+		SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+	SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_SGX_INITIALISED);
+
+//#ifdef SUPPORT_MSVDX
+	eError = PVRSRVInitialiseDevice (gui32MSVDXDeviceID);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialise device!"));
+		SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+	SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_MSVDX_INITIALISED);
+//#endif
+
+	return PVRSRV_OK;
+}
+
+
+static IMG_VOID SysEnableInterrupts(SYS_DATA *psSysData)
+{
+#if !defined(NO_HARDWARE)
+	IMG_UINT32 ui32RegData;
+	IMG_UINT32 ui32Mask;
+
+	ui32Mask = THALIA_MASK | MSVDX_MASK;
+
+	ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_IDENTITY_REG);
+	OSWriteHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_IDENTITY_REG, ui32RegData | ui32Mask);
+
+
+	ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_MASK_REG);
+	OSWriteHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_MASK_REG, ui32RegData & (~ui32Mask));
+
+
+	ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_ENABLE_REG);
+	OSWriteHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_ENABLE_REG, ui32RegData | ui32Mask);
+
+	PVR_TRACE(("SysEnableInterrupts: Interrupts enabled"));
+#endif
+	PVR_UNREFERENCED_PARAMETER(psSysData);
+}
+
+static IMG_VOID SysDisableInterrupts(SYS_DATA *psSysData)
+{
+#if !defined(NO_HARDWARE)
+	IMG_UINT32 ui32RegData;
+	IMG_UINT32 ui32Mask;
+
+
+	ui32Mask = THALIA_MASK | MSVDX_MASK;
+
+	ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_ENABLE_REG);
+	OSWriteHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_ENABLE_REG, ui32RegData & (~ui32Mask));
+
+
+	ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_MASK_REG);
+	OSWriteHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_MASK_REG, ui32RegData | ui32Mask);
+
+	PVR_TRACE(("SysDisableInterrupts: Interrupts disabled"));
+#endif
+	PVR_UNREFERENCED_PARAMETER(psSysData);
+}
+
+IMG_VOID SysReEnableInterrupts(IMG_VOID)
+{
+	SysEnableInterrupts(gpsSysData);
+}
+
+PVRSRV_ERROR SysFinalise(IMG_VOID)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+#if defined(SYS_USING_INTERRUPTS)
+	eError = OSInstallMISR(gpsSysData);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysFinalise: OSInstallMISR failed"));
+		SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+	SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_MISR_INSTALLED);
+
+	eError = OSInstallSystemLISR(gpsSysData, gsSGXDeviceMap.ui32IRQ);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysFinalise: OSInstallSystemLISR failed"));
+		SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+	SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_LISR_INSTALLED);
+#endif
+
+	SysEnableInterrupts(gpsSysData);
+	SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_IRQ_ENABLED);
+
+#ifdef	__linux__
+
+	eError = SysCreateVersionString(gpsSysData);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to create a system version string"));
+	}
+#endif
+
+	return eError;
+}
+
+PVRSRV_ERROR SysDeinitialise (SYS_DATA *psSysData)
+{
+	PVRSRV_ERROR eError;
+
+	SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+	if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_IRQ_ENABLED))
+	{
+		SysDisableInterrupts(psSysData);
+	}
+
+#if defined(SYS_USING_INTERRUPTS)
+	if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_LISR_INSTALLED))
+	{
+		eError = OSUninstallSystemLISR(psSysData);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: OSUninstallSystemLISR failed"));
+			return eError;
+		}
+	}
+
+	if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_MISR_INSTALLED))
+	{
+		eError = OSUninstallMISR(psSysData);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: OSUninstallMISR failed"));
+			return eError;
+		}
+	}
+#endif
+/* Commenting this out to clean up allocation made in SysInitialise */
+/*#if defined(SUPPORT_MSVDX)*/
+	if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_MSVDX_INITIALISED))
+	{
+
+		eError = PVRSRVDeinitialiseDevice(gui32MSVDXDeviceID);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: failed to de-init the device"));
+			return eError;
+		}
+	}
+/*#endif*/
+
+	if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_SGX_INITIALISED))
+	{
+
+		eError = PVRSRVDeinitialiseDevice(gui32SGXDeviceID);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: failed to de-init the device"));
+			return eError;
+		}
+	}
+
+#ifdef __linux__
+	SysFreeVersionString(psSysData);
+
+	PCIDeInitDev(psSysData);
+#endif
+
+	eError = OSDeInitEnvData(psSysData->pvEnvSpecificData);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: failed to de-init env structure"));
+		return eError;
+	}
+
+	SysDeinitialiseCommon(gpsSysData);
+
+#if defined(NO_HARDWARE)
+#ifdef SUPPORT_MSVDX
+	if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_ALLOC_DUMMY_MSVDX_REGS))
+	{
+		OSBaseFreeContigMemory(MSVDX_REG_SIZE, gsMSVDXRegsCPUVAddr, gsMSVDXDeviceMap.sRegsCpuPBase);
+	}
+#endif
+
+	if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_ALLOC_DUMMY_SGX_REGS))
+	{
+		OSBaseFreeContigMemory(SGX_REG_SIZE, gsSGXRegsCPUVAddr, gsSGXDeviceMap.sRegsCpuPBase);
+	}
+#endif
+
+#if !defined(NO_HARDWARE)
+
+	OSUnMapPhysToLin(gsPoulsboRegsCPUVaddr,
+											 REG_SIZE,
+											 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+											 IMG_NULL);
+
+#if defined(MAP_UNUSED_MAPPINGS)
+	OSUnMapPhysToLin(gsPoulsboDisplayRegsCPUVaddr,
+											 DISPLAY_REG_SIZE,
+											 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+											 IMG_NULL);
+#endif
+
+#endif
+	if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_PDUMP_INIT))
+	{
+		PDUMPDEINIT();
+	}
+
+	gpsSysData = IMG_NULL;
+
+	return PVRSRV_OK;
+}
+
+
+IMG_UINT32 SysGetInterruptSource(SYS_DATA* psSysData,
+								 PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+#if !defined(NO_HARDWARE)
+	IMG_UINT32 ui32Devices = 0;
+	IMG_UINT32 ui32Data, ui32DIMMask;
+
+	PVR_UNREFERENCED_PARAMETER(psSysData);
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+
+	ui32Data = OSReadHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_IDENTITY_REG);
+
+	if (ui32Data & THALIA_MASK)
+	{
+		ui32Devices |= DEVICE_SGX_INTERRUPT;
+	}
+
+	if (ui32Data & MSVDX_MASK)
+	{
+		ui32Devices |= DEVICE_MSVDX_INTERRUPT;
+	}
+
+
+	ui32DIMMask = OSReadHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_ENABLE_REG);
+	ui32DIMMask &= ~(THALIA_MASK | MSVDX_MASK);
+
+
+	if (ui32Data & ui32DIMMask)
+	{
+		ui32Devices |= DEVICE_DISP_INTERRUPT;
+	}
+
+	return (ui32Devices);
+#else
+	PVR_UNREFERENCED_PARAMETER(psSysData);
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+	return 0;
+#endif
+}
+
+IMG_VOID SysClearInterrupts(SYS_DATA* psSysData, IMG_UINT32 ui32ClearBits)
+{
+#if !defined(NO_HARDWARE)
+	IMG_UINT32 ui32Data;
+	IMG_UINT32 ui32Mask = 0;
+
+	PVR_UNREFERENCED_PARAMETER(psSysData);
+
+	ui32Data = OSReadHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_STATUS_REG);
+
+	if ((ui32ClearBits & DEVICE_SGX_INTERRUPT) &&
+		((ui32Data & THALIA_MASK) == 0))
+	{
+		ui32Mask |= THALIA_MASK;
+	}
+
+	if ((ui32ClearBits & DEVICE_MSVDX_INTERRUPT) &&
+		((ui32Data & MSVDX_MASK) == 0))
+	{
+		ui32Mask |= MSVDX_MASK;
+	}
+
+	if (ui32Mask)
+	{
+		OSWriteHWReg(gsPoulsboRegsCPUVaddr, INTERRUPT_IDENTITY_REG, ui32Mask);
+	}
+#else
+	PVR_UNREFERENCED_PARAMETER(psSysData);
+	PVR_UNREFERENCED_PARAMETER(ui32ClearBits);
+#endif
+}
+
+
+
+PVRSRV_ERROR SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE eDeviceType,
+									IMG_VOID **ppvDeviceMap)
+{
+
+	switch(eDeviceType)
+	{
+		case PVRSRV_DEVICE_TYPE_SGX:
+		{
+
+			*ppvDeviceMap = (IMG_VOID*)&gsSGXDeviceMap;
+			break;
+		}
+#ifdef SUPPORT_MSVDX
+		case PVRSRV_DEVICE_TYPE_MSVDX:
+		{
+
+			*ppvDeviceMap = (IMG_VOID*)&gsMSVDXDeviceMap;
+			break;
+		}
+#endif
+		default:
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SysGetDeviceMemoryMap: unsupported device type"));
+		}
+	}
+	return PVRSRV_OK;
+}
+
+
+IMG_DEV_PHYADDR SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType,
+										IMG_CPU_PHYADDR CpuPAddr)
+{
+	IMG_DEV_PHYADDR DevPAddr;
+
+	PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+
+	DevPAddr.uiAddr = CpuPAddr.uiAddr;
+
+	return DevPAddr;
+}
+
+
+IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr (IMG_SYS_PHYADDR sys_paddr)
+{
+	IMG_CPU_PHYADDR cpu_paddr;
+
+
+	cpu_paddr.uiAddr = sys_paddr.uiAddr;
+	return cpu_paddr;
+}
+
+IMG_SYS_PHYADDR SysCpuPAddrToSysPAddr (IMG_CPU_PHYADDR cpu_paddr)
+{
+	IMG_SYS_PHYADDR sys_paddr;
+
+
+	sys_paddr.uiAddr = cpu_paddr.uiAddr;
+	return sys_paddr;
+}
+
+
+IMG_DEV_PHYADDR SysSysPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr)
+{
+    IMG_DEV_PHYADDR DevPAddr;
+
+	PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+
+    DevPAddr.uiAddr = SysPAddr.uiAddr;
+
+    return DevPAddr;
+}
+
+
+IMG_SYS_PHYADDR SysDevPAddrToSysPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_DEV_PHYADDR DevPAddr)
+{
+    IMG_SYS_PHYADDR SysPAddr;
+
+	PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+
+    SysPAddr.uiAddr = DevPAddr.uiAddr;
+
+    return SysPAddr;
+}
+
+
+IMG_VOID SysRegisterExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+}
+
+
+IMG_VOID SysRemoveExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+}
+
+PVRSRV_ERROR SysOEMFunction (	IMG_UINT32	ui32ID,
+								IMG_VOID	*pvIn,
+								IMG_UINT32  ulInSize,
+								IMG_VOID	*pvOut,
+								IMG_UINT32	ulOutSize)
+{
+	if (ulInSize || pvIn);
+
+	if ((ui32ID == OEM_GET_EXT_FUNCS) &&
+		(ulOutSize == sizeof(PVRSRV_DC_OEM_JTABLE)))
+	{
+		PVRSRV_DC_OEM_JTABLE *psOEMJTable = (PVRSRV_DC_OEM_JTABLE*)pvOut;
+		psOEMJTable->pfnOEMBridgeDispatch = &PVRSRV_BridgeDispatchKM;
+#ifdef	__linux__
+		psOEMJTable->pfnOEMReadRegistryString  = IMG_NULL;
+		psOEMJTable->pfnOEMWriteRegistryString = IMG_NULL;
+#else
+		psOEMJTable->pfnOEMReadRegistryString  = IMG_NULL;
+		psOEMJTable->pfnOEMWriteRegistryString = IMG_NULL;
+#endif
+		return PVRSRV_OK;
+	}
+
+	return PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+
+
+PVRSRV_ERROR SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState)
+{
+	PVRSRV_ERROR eError= PVRSRV_OK;
+
+	if (eNewPowerState != gpsSysData->eCurrentPowerState)
+	{
+		if ((eNewPowerState == PVRSRV_SYS_POWER_STATE_D3) &&
+			(gpsSysData->eCurrentPowerState < PVRSRV_SYS_POWER_STATE_D3))
+		{
+
+			if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_IRQ_ENABLED))
+			{
+				SysDisableInterrupts(gpsSysData);
+
+				SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_IRQ_DISABLE);
+				SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData, SYS_SPECIFIC_DATA_IRQ_ENABLED);
+			}
+
+#if defined(SYS_USING_INTERRUPTS)
+			if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_LISR_INSTALLED))
+			{
+				eError = OSUninstallSystemLISR(gpsSysData);
+				if (eError != PVRSRV_OK)
+				{
+					PVR_DPF((PVR_DBG_ERROR,"SysSystemPrePowerState: OSUninstallSystemLISR failed (%d)", eError));
+				}
+				SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR);
+				SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData, SYS_SPECIFIC_DATA_LISR_INSTALLED);
+			}
+#endif
+
+
+#ifdef	__linux__
+			eError = OSPCISuspendDev(gsSysSpecificData.hSGXPCI);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SysSystemPrePowerState: OSPCISuspendDev failed (%d)", eError));
+			}
+#endif
+		}
+	}
+
+	return eError;
+}
+
+PVRSRV_ERROR SysSystemPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if (eNewPowerState != gpsSysData->eCurrentPowerState)
+	{
+		if ((gpsSysData->eCurrentPowerState == PVRSRV_SYS_POWER_STATE_D3) &&
+			(eNewPowerState < PVRSRV_SYS_POWER_STATE_D3))
+		{
+#ifdef	__linux__
+			eError = OSPCIResumeDev(gsSysSpecificData.hSGXPCI);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SysSystemPostPowerState: OSPCIResumeDev failed (%d)", eError));
+			}
+#endif
+
+
+#if defined(SYS_USING_INTERRUPTS)
+			if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR))
+			{
+				eError = OSInstallSystemLISR(gpsSysData, gsSGXDeviceMap.ui32IRQ);
+				if (eError != PVRSRV_OK)
+				{
+					PVR_DPF((PVR_DBG_ERROR,"SysSystemPostPowerState: OSInstallSystemLISR failed to install ISR (%d)", eError));
+				}
+				SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_LISR_INSTALLED);
+				SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR);
+			}
+#endif
+
+			if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_IRQ_DISABLE))
+			{
+				SysEnableInterrupts(gpsSysData);
+
+				SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_IRQ_ENABLED);
+				SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_IRQ_DISABLE);
+			}
+		}
+	}
+	return eError;
+}
+
+
+PVRSRV_ERROR SysDevicePrePowerState(IMG_UINT32				ui32DeviceIndex,
+									PVRSRV_DEV_POWER_STATE	eNewPowerState,
+									PVRSRV_DEV_POWER_STATE	eCurrentPowerState)
+{
+	if (ui32DeviceIndex == gui32SGXDeviceID)
+	{
+		if ((eNewPowerState != eCurrentPowerState) &&
+			(eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF))
+		{
+			PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePrePowerState: Remove SGX power"));
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SysDevicePostPowerState(IMG_UINT32				ui32DeviceIndex,
+									 PVRSRV_DEV_POWER_STATE	eNewPowerState,
+									 PVRSRV_DEV_POWER_STATE	eCurrentPowerState)
+{
+	if (ui32DeviceIndex == gui32SGXDeviceID)
+	{
+		if ((eNewPowerState != eCurrentPowerState) &&
+			(eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF))
+		{
+			PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePostPowerState: Restore SGX power"));
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/common/sysutils.c b/drivers/gpu/drm/emgd/pvr/services4/system/common/sysutils.c
new file mode 100644
index 0000000..0e3e7a9
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/common/sysutils.c
@@ -0,0 +1,26 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "sysinfo.h"
+#include "syslocal.h"
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/include/oemfuncs.h b/drivers/gpu/drm/emgd/pvr/services4/system/include/oemfuncs.h
new file mode 100644
index 0000000..343e85f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/include/oemfuncs.h
@@ -0,0 +1,68 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__OEMFUNCS_H__)
+#define __OEMFUNCS_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define OEM_EXCHANGE_POWER_STATE	(1<<0)
+#define OEM_DEVICE_MEMORY_POWER		(1<<1)
+#define OEM_DISPLAY_POWER			(1<<2)
+#define OEM_GET_EXT_FUNCS			(1<<3)
+
+typedef struct OEM_ACCESS_INFO_TAG
+{
+	IMG_UINT32		ui32Size;
+	IMG_UINT32  	ui32FBPhysBaseAddress;
+	IMG_UINT32		ui32FBMemAvailable;
+	IMG_UINT32  	ui32SysPhysBaseAddress;
+	IMG_UINT32		ui32SysSize;
+	IMG_UINT32		ui32DevIRQ;
+} OEM_ACCESS_INFO, *POEM_ACCESS_INFO;
+
+typedef IMG_UINT32   (*PFN_SRV_BRIDGEDISPATCH)( IMG_UINT32  Ioctl,
+												IMG_BYTE   *pInBuf,
+												IMG_UINT32  InBufLen,
+											    IMG_BYTE   *pOutBuf,
+												IMG_UINT32  OutBufLen,
+												IMG_UINT32 *pdwBytesTransferred);
+
+
+typedef PVRSRV_ERROR (*PFN_SRV_READREGSTRING)(PPVRSRV_REGISTRY_INFO psRegInfo);
+
+
+typedef struct PVRSRV_DC_OEM_JTABLE_TAG
+{
+	PFN_SRV_BRIDGEDISPATCH			pfnOEMBridgeDispatch;
+	PFN_SRV_READREGSTRING			pfnOEMReadRegistryString;
+	PFN_SRV_READREGSTRING			pfnOEMWriteRegistryString;
+
+} PVRSRV_DC_OEM_JTABLE;
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/include/sys_pvr_drm_shared.h b/drivers/gpu/drm/emgd/pvr/services4/system/include/sys_pvr_drm_shared.h
new file mode 100644
index 0000000..8ae67dc
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/include/sys_pvr_drm_shared.h
@@ -0,0 +1,34 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__SYS_PVR_DRM_SHARED_H__)
+#define __SYS_PVR_DRM_SHARED_H__
+
+#define	DRM_PSB_GTT_MAP     0x0F
+#define	DRM_PSB_GTT_UNMAP   0x10
+
+/* Note: the ioctl numbers used to be here, but are now defined in the common
+ * header, "emgd_shared.h", to avoid getting out-of-sync:
+ */
+#include "emgd_shared.h"
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/include/syscommon.h b/drivers/gpu/drm/emgd/pvr/services4/system/include/syscommon.h
new file mode 100644
index 0000000..d316141
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/include/syscommon.h
@@ -0,0 +1,27 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+#ifndef _SYSCOMMON_H
+#define _SYSCOMMON_H
+
+#include "sysconfig.h"
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/include/sysconfig.h b/drivers/gpu/drm/emgd/pvr/services4/system/include/sysconfig.h
new file mode 100644
index 0000000..56abae7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/include/sysconfig.h
@@ -0,0 +1,326 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _SYSCONFIG_H
+#define _SYSCONFIG_H
+
+#include "sysinfo.h"
+#include "servicesint.h"
+#include "queue.h"
+#include "power.h"
+#include "resman.h"
+#include "ra.h"
+#include "device.h"
+#include "buffer_manager.h"
+
+
+#if defined(NO_HARDWARE) && defined(__linux__) && defined(__KERNEL__)
+#include <asm/io.h>
+#endif
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef struct _SYS_DEVICE_ID_TAG
+{
+	IMG_UINT32	uiID;
+	IMG_BOOL	bInUse;
+
+} SYS_DEVICE_ID;
+
+
+#define SYS_MAX_LOCAL_DEVMEM_ARENAS	4
+
+typedef struct _SYS_DATA_TAG_
+{
+    IMG_UINT32				ui32NumDevices;
+	SYS_DEVICE_ID			sDeviceID[SYS_DEVICE_COUNT];
+    PVRSRV_DEVICE_NODE		*psDeviceNodeList;
+    PVRSRV_POWER_DEV		*psPowerDeviceList;
+	PVRSRV_RESOURCE			sPowerStateChangeResource;
+	PVRSRV_SYS_POWER_STATE	eCurrentPowerState;
+	PVRSRV_SYS_POWER_STATE	eFailedPowerState;
+	IMG_UINT32		 		ui32CurrentOSPowerState;
+    PVRSRV_QUEUE_INFO		*psQueueList;
+	PVRSRV_KERNEL_SYNC_INFO *psSharedSyncInfoList;
+    IMG_PVOID				pvEnvSpecificData;
+    IMG_PVOID				pvSysSpecificData;
+	PVRSRV_RESOURCE			sQProcessResource;
+	IMG_VOID				*pvSOCRegsBase;
+    IMG_HANDLE				hSOCTimerRegisterOSMemHandle;
+	IMG_UINT32				*pvSOCTimerRegisterKM;
+	IMG_VOID				*pvSOCClockGateRegsBase;
+	IMG_UINT32				ui32SOCClockGateRegsSize;
+	PFN_CMD_PROC			*ppfnCmdProcList[SYS_DEVICE_COUNT];
+
+
+	PCOMMAND_COMPLETE_DATA	*ppsCmdCompleteData[SYS_DEVICE_COUNT];
+
+	IMG_BOOL				bReProcessQueues;
+
+	RA_ARENA				*apsLocalDevMemArena[SYS_MAX_LOCAL_DEVMEM_ARENAS];
+
+    IMG_CHAR				*pszVersionString;
+	PVRSRV_EVENTOBJECT		*psGlobalEventObject;
+
+	IMG_BOOL				bFlushAll;
+
+} SYS_DATA;
+
+
+
+PVRSRV_ERROR SysInitialise(IMG_VOID);
+PVRSRV_ERROR SysFinalise(IMG_VOID);
+
+IMG_VOID SysReEnableInterrupts(IMG_VOID);
+
+PVRSRV_ERROR SysDeinitialise(SYS_DATA *psSysData);
+PVRSRV_ERROR SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE eDeviceType,
+									IMG_VOID **ppvDeviceMap);
+
+IMG_VOID SysRegisterExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_VOID SysRemoveExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_UINT32 SysGetInterruptSource(SYS_DATA			*psSysData,
+								 PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_VOID SysClearInterrupts(SYS_DATA* psSysData, IMG_UINT32 ui32ClearBits);
+
+PVRSRV_ERROR SysResetDevice(IMG_UINT32 ui32DeviceIndex);
+
+PVRSRV_ERROR SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState);
+PVRSRV_ERROR SysSystemPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState);
+PVRSRV_ERROR SysDevicePrePowerState(IMG_UINT32 ui32DeviceIndex,
+									PVRSRV_DEV_POWER_STATE eNewPowerState,
+									PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR SysDevicePostPowerState(IMG_UINT32 ui32DeviceIndex,
+									 PVRSRV_DEV_POWER_STATE eNewPowerState,
+									 PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+PVRSRV_ERROR SysPowerLockWrap(SYS_DATA *psSysData);
+IMG_VOID SysPowerLockUnwrap(SYS_DATA *psSysData);
+#endif
+PVRSRV_ERROR SysOEMFunction(		IMG_UINT32 ui32ID,
+						IMG_VOID *pvIn,
+						IMG_UINT32 ulInSize,
+						IMG_VOID *pvOut,
+						IMG_UINT32 ulOutSize);
+IMG_DEV_PHYADDR SysCpuPAddrToDevPAddr(	PVRSRV_DEVICE_TYPE eDeviceType,
+						IMG_CPU_PHYADDR cpu_paddr);
+IMG_DEV_PHYADDR SysSysPAddrToDevPAddr(	PVRSRV_DEVICE_TYPE eDeviceType,
+						IMG_SYS_PHYADDR SysPAddr);
+IMG_SYS_PHYADDR SysDevPAddrToSysPAddr(	PVRSRV_DEVICE_TYPE eDeviceType,
+						IMG_DEV_PHYADDR SysPAddr);
+IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr(	IMG_SYS_PHYADDR SysPAddr);
+IMG_SYS_PHYADDR SysCpuPAddrToSysPAddr(	IMG_CPU_PHYADDR cpu_paddr);
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis  platform interface definition
+*/
+/* ----------------------------------------------------------------------------*/
+typedef struct _SYS_PLATFORM_INTERFACE {
+	char* 		sProductName;
+	IMG_UINT32	uiSgxDevDeviceID;
+	IMG_UINT32	uiSgxRegsOffset;
+	IMG_UINT32	uiMsvdxRegsOffset;
+	IMG_UINT32	uiSysSgxClockSpeed;
+	IMG_UINT32	uiSysSgxActivePowerLatencyMs;
+} SYS_PLATFORM_INTERFACE;
+
+/* #define MAP_UNUSED_MAPPINGS */
+
+#if defined(MAP_UNUSED_MAPPINGS)
+#define SGX_FEATURE_HOST_PORT
+#endif
+
+extern SYS_PLATFORM_INTERFACE *gpsSysPlatformInterface;
+
+#define VS_PRODUCT_NAME  	((gpsSysPlatformInterface) ? (gpsSysPlatformInterface->sProductName) : "Unknown Product")
+#define SYS_SGX_DEV_DEVICE_ID  	((gpsSysPlatformInterface) ? (gpsSysPlatformInterface->uiSgxDevDeviceID) : 0x0)
+#define SGX_REGS_OFFSET  	((gpsSysPlatformInterface) ? (gpsSysPlatformInterface->uiSgxRegsOffset) : 0x0)
+#ifdef SUPPORT_MSVDX
+#define MSVDX_REGS_OFFSET  	((gpsSysPlatformInterface) ? (gpsSysPlatformInterface->uiMsvdxRegsOffset) : 0x0)
+#endif
+#define SYS_SGX_CLOCK_SPEED 	((gpsSysPlatformInterface) ? (gpsSysPlatformInterface->uiSysSgxClockSpeed) : 0)
+#define SYS_SGX_ACTIVE_POWER_LATENCY_MS ((gpsSysPlatformInterface) ? (gpsSysPlatformInterface->uiSysSgxActivePowerLatencyMs) : 0)
+
+#define SYS_SGX_DEV_VENDOR_ID           0x8086
+
+#define SYS_SGX_HWRECOVERY_TIMEOUT_FREQ         (100)
+#define SYS_SGX_PDS_TIMER_FREQ                  (1000)
+
+
+#define REGS_OFFSET	0x00000
+#define REG_SIZE	0x2100
+
+#define SGX_REG_SIZE 		0x4000
+
+#ifdef SUPPORT_MSVDX
+#define	MAX_OFFSET	(MSVDX_REGS_OFFSET + MSVDX_REG_SIZE)
+#else
+#define	MAX_OFFSET	(SGX_REGS_OFFSET + SGX_REG_SIZE)
+#endif
+
+#define MMADR_INDEX			4
+
+#define DEVICE_SGX_INTERRUPT		(1UL<<0)
+#define DEVICE_MSVDX_INTERRUPT		(1UL<<1)
+#define DEVICE_DISP_INTERRUPT		(1UL<<2)
+
+#define INTERRUPT_ENABLE_REG		0x20A0
+#define INTERRUPT_IDENTITY_REG		0x20A4
+#define INTERRUPT_MASK_REG			0x20A8
+#define INTERRUPT_STATUS_REG		0x20AC
+
+#define DISP_MASK					(1UL<<17)
+#define THALIA_MASK					(1UL<<18)
+#define MSVDX_MASK					(1UL<<19)
+#define VSYNC_PIPEA_VBLANK_MASK		(1UL<<7)
+#define VSYNC_PIPEA_EVENT_MASK		(1UL<<6)
+#define VSYNC_PIPEB_VBLANK_MASK		(1UL<<5)
+#define VSYNC_PIPEB_EVENT_MASK		(1UL<<4)
+
+#define DISPLAY_REGS_OFFSET			0x70000
+#define DISPLAY_REG_SIZE			0x2000
+
+#define DISPLAY_A_CONFIG			0x00008UL
+#define DISPLAY_A_STATUS_SELECT		0x00024UL
+#define DISPLAY_B_CONFIG			0x01008UL
+#define DISPLAY_B_STATUS_SELECT		0x01024UL
+
+#define DISPLAY_PIPE_ENABLE			(1UL<<31)
+#define DISPLAY_VSYNC_STS_EN		(1UL<<25)
+#define DISPLAY_VSYNC_STS			(1UL<<9)
+
+#if defined(SGX_FEATURE_HOST_PORT)
+	#define SYS_SGX_HP_SIZE		0x8000000
+
+	#define SYS_SGX_HOSTPORT_BASE_DEVVADDR 0xD0000000
+	#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030)
+		#define SYS_SGX_HOSTPORT_BRN23030_OFFSET 0x7C00000
+	#endif
+#endif
+
+
+typedef struct
+{
+	union
+	{
+#if !defined(VISTA)
+		IMG_UINT8	aui8PCISpace[256];
+		IMG_UINT16	aui16PCISpace[128];
+		IMG_UINT32	aui32PCISpace[64];
+#endif
+		struct
+		{
+			IMG_UINT16	ui16VenID;
+			IMG_UINT16	ui16DevID;
+			IMG_UINT16	ui16PCICmd;
+			IMG_UINT16	ui16PCIStatus;
+		}s;
+	}u;
+} PCICONFIG_SPACE, *PPCICONFIG_SPACE;
+
+
+extern SYS_DATA* gpsSysData;
+
+PVRSRV_ERROR SysResetDevice(IMG_UINT32 ui32DeviceIndex);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+PVRSRV_ERROR SysPowerLockWrap(SYS_DATA *psSysData);
+IMG_VOID SysPowerLockUnwrap(SYS_DATA *psSysData);
+#endif
+
+
+#if defined(PVR_LMA)
+IMG_BOOL SysVerifyCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_CPU_PHYADDR CpuPAddr);
+IMG_BOOL SysVerifySysPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr);
+#endif
+
+extern SYS_DATA* gpsSysData;
+
+#if !defined(USE_CODE)
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysAcquireData)
+#endif
+static INLINE PVRSRV_ERROR SysAcquireData(SYS_DATA **ppsSysData)
+{
+
+	*ppsSysData = gpsSysData;
+
+	if (!gpsSysData)
+	{
+		return PVRSRV_ERROR_GENERIC;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysInitialiseCommon)
+#endif
+static INLINE PVRSRV_ERROR SysInitialiseCommon(SYS_DATA *psSysData)
+{
+	PVRSRV_ERROR	eError;
+	eError = PVRSRVInit(psSysData);
+
+	return eError;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysDeinitialiseCommon)
+#endif
+static INLINE IMG_VOID SysDeinitialiseCommon(SYS_DATA *psSysData)
+{
+	PVRSRVDeInit(psSysData);
+
+	OSDestroyResource(&psSysData->sPowerStateChangeResource);
+}
+#endif
+
+
+#if !(defined(NO_HARDWARE) && defined(__linux__) && defined(__KERNEL__))
+#define	SysReadHWReg(p, o) OSReadHWReg(p, o)
+#define SysWriteHWReg(p, o, v) OSWriteHWReg(p, o, v)
+#else
+static inline IMG_UINT32 SysReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+	return (IMG_UINT32) readl(pvLinRegBaseAddr + ui32Offset);
+}
+
+static inline IMG_VOID SysWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+	writel(ui32Value, pvLinRegBaseAddr + ui32Offset);
+}
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/include/sysinfo.h b/drivers/gpu/drm/emgd/pvr/services4/system/include/sysinfo.h
new file mode 100644
index 0000000..95724d0
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/include/sysinfo.h
@@ -0,0 +1,42 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__SYSINFO_H__)
+#define __SYSINFO_H__
+
+#define MAX_HW_TIME_US				(500000)
+#define WAIT_TRY_COUNT				(10000)
+
+typedef enum _SYS_DEVICE_TYPE_
+{
+	SYS_DEVICE_SGX						= 0,
+
+	SYS_DEVICE_FORCE_I16 				= 0x7fff
+
+} SYS_DEVICE_TYPE;
+#if 0
+#define SYS_DEVICE_COUNT 5
+#endif
+
+#define SYS_DEVICE_COUNT 11
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/include/syslocal.h b/drivers/gpu/drm/emgd/pvr/services4/system/include/syslocal.h
new file mode 100644
index 0000000..59d80da
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/include/syslocal.h
@@ -0,0 +1,80 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#if !defined(__SYSLOCAL_H__)
+#define __SYSLOCAL_H__
+
+#define SYS_SPECIFIC_DATA_PCI_ACQUIRE_DEV		0x00000001UL
+#define SYS_SPECIFIC_DATA_PCI_REQUEST_SGX_ADDR_RANGE	0x00000002UL
+#define SYS_SPECIFIC_DATA_PCI_REQUEST_HOST_PORT_RANGE	0x00000004UL
+#if defined(NO_HARDWARE)
+#define SYS_SPECIFIC_DATA_ALLOC_DUMMY_SGX_REGS		0x00000008UL
+#if defined(SUPPORT_MSVDX)
+#define	SYS_SPECIFIC_DATA_ALLOC_DUMMY_MSVDX_REGS	0x00000020UL
+#endif
+#endif
+#define	SYS_SPECIFIC_DATA_SGX_INITIALISED		0x00000040UL
+//#if defined(SUPPORT_MSVDX)
+#define	SYS_SPECIFIC_DATA_MSVDX_INITIALISED		0x00000080UL
+//#endif
+#define	SYS_SPECIFIC_DATA_MISR_INSTALLED		0x00000100UL
+#define	SYS_SPECIFIC_DATA_LISR_INSTALLED		0x00000200UL
+#define	SYS_SPECIFIC_DATA_PDUMP_INIT			0x00000400UL
+#define	SYS_SPECIFIC_DATA_IRQ_ENABLED			0x00000800UL
+
+#define	SYS_SPECIFIC_DATA_PM_UNMAP_SGX_REGS		0x00001000UL
+#define	SYS_SPECIFIC_DATA_PM_UNMAP_SGX_HP		0x00004000UL
+#define	SYS_SPECIFIC_DATA_PM_UNMAP_MSVDX_REGS		0x00008000UL
+#define	SYS_SPECIFIC_DATA_PM_IRQ_DISABLE		0x00010000UL
+#define	SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR		0x00020000UL
+
+#define	SYS_SPECIFIC_DATA_SET(psSysSpecData, flag) ((IMG_VOID)((psSysSpecData)->ui32SysSpecificData |= (flag)))
+
+#define	SYS_SPECIFIC_DATA_CLEAR(psSysSpecData, flag) ((IMG_VOID)((psSysSpecData)->ui32SysSpecificData &= ~(flag)))
+
+#define	SYS_SPECIFIC_DATA_TEST(psSysSpecData, flag) (((psSysSpecData)->ui32SysSpecificData & (flag)) != 0)
+
+
+typedef struct _SYS_SPECIFIC_DATA_TAG_
+{
+
+	IMG_UINT32 ui32SysSpecificData;
+#ifdef	__linux__
+	PVRSRV_PCI_DEV_HANDLE hSGXPCI;
+#endif
+#ifdef	LDM_PCI
+	struct pci_dev *psPCIDev;
+#endif
+#ifdef	SUPPORT_DRI_DRM_EXT
+
+	IMG_UINT32 msi_addr;
+	IMG_UINT32 msi_data;
+
+	IMG_UINT32 saveBSM;
+	IMG_UINT32 saveVBT;
+#endif
+} SYS_SPECIFIC_DATA;
+
+
+#endif
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/plb/sysconfig.c b/drivers/gpu/drm/emgd/pvr/services4/system/plb/sysconfig.c
new file mode 100644
index 0000000..ec0222c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/plb/sysconfig.c
@@ -0,0 +1,48 @@
+/* -*- syscommon-c -*-
+ *-----------------------------------------------------------------------------
+ * Filename: syscommon.c
+ * $Revision: 1.4 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description: platform detection, and sharing of correct platform interface.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#include "sysconfig.h"
+#include "sysplb.h"
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Poulsbo platform interface.
+*/
+/* --------------------------------------------------------------------------*/
+SYS_PLATFORM_INTERFACE gpsSysPlatformInterfacePlb = {
+        VS_PRODUCT_NAME_PLB,
+        SYS_SGX_DEV_DEVICE_ID_PLB,
+	SGX_REGS_OFFSET_PLB,
+	MSVDX_REGS_OFFSET_PLB,
+	SYS_SGX_CLOCK_SPEED_PLB,
+	SYS_SGX_ACTIVE_POWER_LATENCY_MS_PLB
+};
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/plb/sysplb.h b/drivers/gpu/drm/emgd/pvr/services4/system/plb/sysplb.h
new file mode 100644
index 0000000..0f7deff
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/plb/sysplb.h
@@ -0,0 +1,33 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _SYSPLB_H
+#define _SYSPLB_H
+
+#define SYS_SGX_DEV_DEVICE_ID_PLB	0x8108
+#define VS_PRODUCT_NAME_PLB     	"SGX Poulsbo"
+#define SGX_REGS_OFFSET_PLB     	0x40000
+#define MSVDX_REGS_OFFSET_PLB   	0x50000
+#define SYS_SGX_CLOCK_SPEED_PLB                     (200000000)
+#define SYS_SGX_ACTIVE_POWER_LATENCY_MS_PLB         (1)
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/tnc/sysconfig.c b/drivers/gpu/drm/emgd/pvr/services4/system/tnc/sysconfig.c
new file mode 100644
index 0000000..09e7997
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/tnc/sysconfig.c
@@ -0,0 +1,48 @@
+/* -*- syscommon-c -*-
+ *-----------------------------------------------------------------------------
+ * Filename: syscommon.c
+ * $Revision: 1.4 $
+ *-----------------------------------------------------------------------------
+ * Copyright (c) 2002-2010, Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *-----------------------------------------------------------------------------
+ * Description: platform detection, and sharing of correct platform interface.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#include "sysconfig.h"
+#include "systnc.h"
+
+/* --------------------------------------------------------------------------*/
+/**
+* @Synopsis Poulsbo platform interface.
+*/
+/* --------------------------------------------------------------------------*/
+SYS_PLATFORM_INTERFACE gpsSysPlatformInterfaceTnc = {
+        VS_PRODUCT_NAME_TNC,
+        SYS_SGX_DEV_DEVICE_ID_TNC,
+	SGX_REGS_OFFSET_TNC,
+	MSVDX_REGS_OFFSET_TNC,
+	SYS_SGX_CLOCK_SPEED_TNC,
+	SYS_SGX_ACTIVE_POWER_LATENCY_MS_TNC
+};
+
diff --git a/drivers/gpu/drm/emgd/pvr/services4/system/tnc/systnc.h b/drivers/gpu/drm/emgd/pvr/services4/system/tnc/systnc.h
new file mode 100644
index 0000000..5793535
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/services4/system/tnc/systnc.h
@@ -0,0 +1,33 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _SYSTNC_H
+#define _SYSTNC_H
+
+#define SYS_SGX_DEV_DEVICE_ID_TNC	0x4108
+#define VS_PRODUCT_NAME_TNC     	"SGX Atom E6xx"
+#define SGX_REGS_OFFSET_TNC     	0x80000
+#define MSVDX_REGS_OFFSET_TNC   	0x90000
+#define SYS_SGX_CLOCK_SPEED_TNC                     (400000000)
+#define SYS_SGX_ACTIVE_POWER_LATENCY_MS_TNC         (50)
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/client/linuxsrv.h b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/client/linuxsrv.h
new file mode 100644
index 0000000..aa43db5
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/client/linuxsrv.h
@@ -0,0 +1,44 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _LINUXSRV_H__
+#define _LINUXSRV_H__
+
+typedef struct tagIOCTL_PACKAGE
+{
+	IMG_UINT32 ui32Cmd;
+	IMG_UINT32 ui32Size;
+	IMG_VOID 	*pInBuffer;
+	IMG_UINT32  ui32InBufferSize;
+	IMG_VOID    *pOutBuffer;
+	IMG_UINT32  ui32OutBufferSize;
+} IOCTL_PACKAGE;
+
+IMG_UINT32 DeviceIoControl(IMG_UINT32 hDevice,
+						IMG_UINT32 ui32ControlCode,
+						IMG_VOID *pInBuffer,
+						IMG_UINT32 ui32InBufferSize,
+						IMG_VOID *pOutBuffer,
+						IMG_UINT32 ui32OutBufferSize,
+						IMG_UINT32 *pui32BytesReturned);
+
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.c b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.c
new file mode 100644
index 0000000..d317957
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.c
@@ -0,0 +1,2072 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+
+#ifdef LINUX
+#include <linux/string.h>
+#endif
+
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+#include "hostfunc.h"
+
+
+
+
+#define LAST_FRAME_BUF_SIZE	1024
+
+typedef struct _DBG_LASTFRAME_BUFFER_
+{
+	PDBG_STREAM	psStream;
+	IMG_UINT8 ui8Buffer[LAST_FRAME_BUF_SIZE];
+	IMG_UINT32		ui32BufLen;
+	struct _DBG_LASTFRAME_BUFFER_	*psNext;
+} *PDBG_LASTFRAME_BUFFER;
+
+
+static PDBG_STREAM	g_psStreamList = 0;
+static PDBG_LASTFRAME_BUFFER	g_psLFBufferList;
+
+static IMG_UINT32		g_ui32LOff = 0;
+static IMG_UINT32		g_ui32Line = 0;
+static IMG_UINT32		g_ui32MonoLines = 25;
+
+static IMG_BOOL			g_bHotkeyMiddump = IMG_FALSE;
+static IMG_UINT32		g_ui32HotkeyMiddumpStart = 0xffffffff;
+static IMG_UINT32		g_ui32HotkeyMiddumpEnd = 0xffffffff;
+
+IMG_VOID *				g_pvAPIMutex=IMG_NULL;
+
+extern IMG_UINT32		g_ui32HotKeyFrame;
+extern IMG_BOOL			g_bHotKeyPressed;
+extern IMG_BOOL			g_bHotKeyRegistered;
+
+IMG_BOOL				gbDumpThisFrame = IMG_FALSE;
+
+
+IMG_UINT32 SpaceInStream(PDBG_STREAM psStream);
+IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize);
+PDBG_LASTFRAME_BUFFER FindLFBuf(PDBG_STREAM psStream);
+
+DBGKM_SERVICE_TABLE g_sDBGKMServices =
+{
+	sizeof (DBGKM_SERVICE_TABLE),
+	ExtDBGDrivCreateStream,
+	ExtDBGDrivDestroyStream,
+	ExtDBGDrivFindStream,
+	ExtDBGDrivWriteString,
+	ExtDBGDrivReadString,
+	ExtDBGDrivWrite,
+	ExtDBGDrivRead,
+	ExtDBGDrivSetCaptureMode,
+	ExtDBGDrivSetOutputMode,
+	ExtDBGDrivSetDebugLevel,
+	ExtDBGDrivSetFrame,
+	ExtDBGDrivGetFrame,
+	ExtDBGDrivOverrideMode,
+	ExtDBGDrivDefaultMode,
+	ExtDBGDrivWrite2,
+	ExtDBGDrivWriteStringCM,
+	ExtDBGDrivWriteCM,
+	ExtDBGDrivSetMarker,
+	ExtDBGDrivGetMarker,
+	ExtDBGDrivStartInitPhase,
+	ExtDBGDrivStopInitPhase,
+	ExtDBGDrivIsCaptureFrame,
+	ExtDBGDrivWriteLF,
+	ExtDBGDrivReadLF,
+	ExtDBGDrivGetStreamOffset,
+	ExtDBGDrivSetStreamOffset,
+	ExtDBGDrivIsLastCaptureFrame,
+	ExtDBGDrivWaitForEvent
+};
+
+
+
+
+
+IMG_VOID * IMG_CALLCONV ExtDBGDrivCreateStream(IMG_CHAR *	pszName, IMG_UINT32 ui32CapMode, IMG_UINT32	ui32OutMode, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size)
+{
+	IMG_VOID *	pvRet;
+
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	pvRet=DBGDrivCreateStream(pszName, ui32CapMode, ui32OutMode, ui32Flags, ui32Size);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return pvRet;
+}
+
+void IMG_CALLCONV ExtDBGDrivDestroyStream(PDBG_STREAM psStream)
+{
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	DBGDrivDestroyStream(psStream);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return;
+}
+
+IMG_VOID * IMG_CALLCONV ExtDBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
+{
+	IMG_VOID *	pvRet;
+
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	pvRet=DBGDrivFindStream(pszName, bResetStream);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return pvRet;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+	IMG_UINT32	ui32Ret;
+
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	ui32Ret=DBGDrivWriteString(psStream, pszString, ui32Level);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit)
+{
+	IMG_UINT32 ui32Ret;
+
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	ui32Ret=DBGDrivReadString(psStream, pszString, ui32Limit);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+	IMG_UINT32	ui32Ret;
+
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	ui32Ret=DBGDrivWrite(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivRead(PDBG_STREAM psStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
+{
+	IMG_UINT32 ui32Ret;
+
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	ui32Ret=DBGDrivRead(psStream, bReadInitBuffer, ui32OutBuffSize, pui8OutBuf);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return ui32Ret;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate)
+{
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	DBGDrivSetCaptureMode(psStream, ui32Mode, ui32Start, ui32End, ui32SampleRate);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode)
+{
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	DBGDrivSetOutputMode(psStream, ui32OutMode);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel)
+{
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	DBGDrivSetDebugLevel(psStream, ui32DebugLevel);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame)
+{
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	DBGDrivSetFrame(psStream, ui32Frame);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetFrame(PDBG_STREAM psStream)
+{
+	IMG_UINT32	ui32Ret;
+
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	ui32Ret=DBGDrivGetFrame(psStream);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return ui32Ret;
+}
+
+IMG_BOOL IMG_CALLCONV ExtDBGDrivIsLastCaptureFrame(PDBG_STREAM psStream)
+{
+	IMG_BOOL	bRet;
+
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	bRet = DBGDrivIsLastCaptureFrame(psStream);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return bRet;
+}
+
+IMG_BOOL IMG_CALLCONV ExtDBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame)
+{
+	IMG_BOOL	bRet;
+
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	bRet = DBGDrivIsCaptureFrame(psStream, bCheckPreviousFrame);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return bRet;
+}
+
+void IMG_CALLCONV ExtDBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode)
+{
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	DBGDrivOverrideMode(psStream, ui32Mode);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return;
+}
+
+void IMG_CALLCONV ExtDBGDrivDefaultMode(PDBG_STREAM psStream)
+{
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	DBGDrivDefaultMode(psStream);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+	IMG_UINT32	ui32Ret;
+
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	ui32Ret=DBGDrivWrite2(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+	IMG_UINT32	ui32Ret;
+
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	ui32Ret=DBGDrivWriteStringCM(psStream, pszString, ui32Level);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+	IMG_UINT32	ui32Ret;
+
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	ui32Ret=DBGDrivWriteCM(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return ui32Ret;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	DBGDrivSetMarker(psStream, ui32Marker);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetMarker(PDBG_STREAM psStream)
+{
+	IMG_UINT32	ui32Marker;
+
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	ui32Marker = DBGDrivGetMarker(psStream);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return ui32Marker;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 * pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags)
+{
+	IMG_UINT32	ui32Ret;
+
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	ui32Ret = DBGDrivWriteLF(psStream, pui8InBuf, ui32InBuffSize, ui32Level, ui32Flags);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 * pui8OutBuf)
+{
+	IMG_UINT32 ui32Ret;
+
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	ui32Ret = DBGDrivReadLF(psStream, ui32OutBuffSize, pui8OutBuf);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return ui32Ret;
+}
+
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivStartInitPhase(PDBG_STREAM psStream)
+{
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	DBGDrivStartInitPhase(psStream);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return;
+}
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivStopInitPhase(PDBG_STREAM psStream)
+{
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	DBGDrivStopInitPhase(psStream);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetStreamOffset(PDBG_STREAM psStream)
+{
+	IMG_UINT32 ui32Ret;
+
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	ui32Ret = DBGDrivGetStreamOffset(psStream);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+
+	return ui32Ret;
+}
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetStreamOffset(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset)
+{
+
+	HostAquireMutex(g_pvAPIMutex);
+
+	DBGDrivSetStreamOffset(psStream, ui32StreamOffset);
+
+
+	HostReleaseMutex(g_pvAPIMutex);
+}
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivWaitForEvent(DBG_EVENT eEvent)
+{
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+	DBGDrivWaitForEvent(eEvent);
+#else
+	PVR_UNREFERENCED_PARAMETER(eEvent);
+#endif
+}
+
+IMG_UINT32 AtoI(IMG_CHAR *szIn)
+{
+	IMG_INT		iLen = 0;
+	IMG_UINT32	ui32Value = 0;
+	IMG_UINT32	ui32Digit=1;
+	IMG_UINT32	ui32Base=10;
+	IMG_INT		iPos;
+	IMG_CHAR	bc;
+
+
+	while (szIn[iLen] > 0)
+	{
+		iLen ++;
+	}
+
+
+	if (iLen == 0)
+	{
+		return (0);
+	}
+
+
+	iPos=0;
+	while (szIn[iPos] == '0')
+	{
+		iPos++;
+	}
+	if (szIn[iPos] == '\0')
+	{
+		return 0;
+	}
+	if (szIn[iPos] == 'x' || szIn[iPos] == 'X')
+	{
+		ui32Base=16;
+		szIn[iPos]='0';
+	}
+
+
+	for (iPos = iLen - 1; iPos >= 0; iPos --)
+	{
+		bc = szIn[iPos];
+
+		if ( (bc >= 'a') && (bc <= 'f') && ui32Base == 16)
+		{
+			bc -= 'a' - 0xa;
+		}
+		else
+		if ( (bc >= 'A') && (bc <= 'F') && ui32Base == 16)
+		{
+			bc -= 'A' - 0xa;
+		}
+		else
+		if ((bc >= '0') && (bc <= '9'))
+		{
+			bc -= '0';
+		}
+		else
+			return (0);
+
+		ui32Value += (IMG_UINT32)bc  * ui32Digit;
+
+		ui32Digit = ui32Digit * ui32Base;
+	}
+	return (ui32Value);
+}
+
+
+IMG_BOOL StreamValid(PDBG_STREAM psStream)
+{
+	PDBG_STREAM	psThis;
+
+	psThis = g_psStreamList;
+
+	while (psThis)
+	{
+		if (psStream && (psThis == psStream))
+		{
+			return(IMG_TRUE);
+		}
+		else
+		{
+			psThis = psThis->psNext;
+		}
+	}
+
+	return(IMG_FALSE);
+}
+
+
+void Write(PDBG_STREAM psStream,IMG_UINT8 * pui8Data,IMG_UINT32 ui32InBuffSize)
+{
+
+
+	if ((psStream->ui32WPtr + ui32InBuffSize) > psStream->ui32Size)
+	{
+		IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32WPtr;
+		IMG_UINT32 ui32B2 = ui32InBuffSize - ui32B1;
+
+
+		HostMemCopy((IMG_VOID *)(psStream->ui32Base + psStream->ui32WPtr),
+				(IMG_VOID *) pui8Data,
+				ui32B1);
+
+
+		HostMemCopy((IMG_VOID *)psStream->ui32Base,
+				(IMG_VOID *)((IMG_UINT32) pui8Data + ui32B1),
+				ui32B2);
+
+
+		psStream->ui32WPtr = ui32B2;
+	}
+	else
+	{
+		HostMemCopy((IMG_VOID *)(psStream->ui32Base + psStream->ui32WPtr),
+				(IMG_VOID *) pui8Data,
+				ui32InBuffSize);
+
+		psStream->ui32WPtr += ui32InBuffSize;
+
+		if (psStream->ui32WPtr == psStream->ui32Size)
+		{
+			psStream->ui32WPtr = 0;
+		}
+	}
+	psStream->ui32DataWritten += ui32InBuffSize;
+}
+
+
+void MonoOut(IMG_CHAR * pszString,IMG_BOOL bNewLine)
+{
+	IMG_UINT32 	i;
+	IMG_CHAR *	pScreen;
+
+	pScreen = (IMG_CHAR *) DBGDRIV_MONOBASE;
+
+	pScreen += g_ui32Line * 160;
+
+
+
+	i=0;
+	do
+	{
+		pScreen[g_ui32LOff + (i*2)] = pszString[i];
+		pScreen[g_ui32LOff + (i*2)+1] = 127;
+		i++;
+	}
+	while ((pszString[i] != 0) && (i < 4096));
+
+	g_ui32LOff += i * 2;
+
+	if (bNewLine)
+	{
+		g_ui32LOff = 0;
+		g_ui32Line++;
+	}
+
+
+
+	if (g_ui32Line == g_ui32MonoLines)
+	{
+		g_ui32Line = g_ui32MonoLines - 1;
+
+		HostMemCopy((IMG_VOID *)DBGDRIV_MONOBASE,(IMG_VOID *)(DBGDRIV_MONOBASE + 160),160 * (g_ui32MonoLines - 1));
+
+		HostMemSet((IMG_VOID *)(DBGDRIV_MONOBASE + (160 * (g_ui32MonoLines - 1))),0,160);
+	}
+}
+
+
+
+void AppendName(IMG_CHAR * pszOut,IMG_CHAR * pszBase,IMG_CHAR * pszName)
+{
+	IMG_UINT32 i;
+	IMG_UINT32 ui32Off;
+
+	i = 0;
+
+	while (pszBase[i] != 0)
+	{
+		pszOut[i] = pszBase[i];
+		i++;
+	}
+
+	ui32Off = i;
+	i = 0;
+
+	while (pszName[i] != 0)
+	{
+		pszOut[ui32Off+i] = pszName[i];
+		i++;
+	}
+
+	pszOut[ui32Off+i] = pszName[i];
+}
+
+
+IMG_VOID * IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR *		pszName,
+								   IMG_UINT32 	ui32CapMode,
+								   IMG_UINT32 	ui32OutMode,
+								   IMG_UINT32	ui32Flags,
+								   IMG_UINT32 	ui32Size)
+{
+	PDBG_STREAM	psStream;
+	PDBG_STREAM	psInitStream;
+	PDBG_LASTFRAME_BUFFER	psLFBuffer;
+	IMG_UINT32		ui32Off;
+	IMG_VOID *		pvBase;
+
+
+
+
+	psStream = (PDBG_STREAM) DBGDrivFindStream(pszName, IMG_FALSE);
+
+	if (psStream)
+	{
+		return ((IMG_VOID *) psStream);
+	}
+
+
+
+	psStream = HostNonPageablePageAlloc(1);
+	psInitStream = HostNonPageablePageAlloc(1);
+	psLFBuffer = HostNonPageablePageAlloc(1);
+	if	(
+			(!psStream) ||
+			(!psInitStream) ||
+			(!psLFBuffer)
+		)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc control structs\n\r"));
+		return((IMG_VOID *) 0);
+	}
+
+
+	if ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+	{
+		pvBase = HostNonPageablePageAlloc(ui32Size);
+	}
+	else
+	{
+		pvBase = HostPageablePageAlloc(ui32Size);
+	}
+
+	if (!pvBase)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc Stream buffer\n\r"));
+		HostNonPageablePageFree(psStream);
+		return((IMG_VOID *) 0);
+	}
+
+
+
+	psStream->psNext = 0;
+	psStream->ui32Flags = ui32Flags;
+	psStream->ui32Base = (IMG_UINT32)pvBase;
+	psStream->ui32Size = ui32Size * 4096UL;
+	psStream->ui32RPtr = 0;
+	psStream->ui32WPtr = 0;
+	psStream->ui32DataWritten = 0;
+	psStream->ui32CapMode = ui32CapMode;
+	psStream->ui32OutMode = ui32OutMode;
+	psStream->ui32DebugLevel = DEBUG_LEVEL_0;
+	psStream->ui32DefaultMode = ui32CapMode;
+	psStream->ui32Start = 0;
+	psStream->ui32End = 0;
+	psStream->ui32Current = 0;
+	psStream->ui32SampleRate = 1;
+	psStream->ui32Access = 0;
+	psStream->ui32Timeout = 0;
+	psStream->ui32Marker = 0;
+	psStream->bInitPhaseComplete = IMG_FALSE;
+
+
+	if ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+	{
+		pvBase = HostNonPageablePageAlloc(ui32Size);
+	}
+	else
+	{
+		pvBase = HostPageablePageAlloc(ui32Size);
+	}
+
+	if (!pvBase)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc InitStream buffer\n\r"));
+
+		if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+		{
+			HostNonPageablePageFree((IMG_VOID *)psStream->ui32Base);
+		}
+		else
+		{
+			HostPageablePageFree((IMG_VOID *)psStream->ui32Base);
+		}
+		HostNonPageablePageFree(psStream);
+		return((IMG_VOID *) 0);
+	}
+
+	psInitStream->psNext = 0;
+	psInitStream->ui32Flags = ui32Flags;
+	psInitStream->ui32Base = (IMG_UINT32)pvBase;
+	psInitStream->ui32Size = ui32Size * 4096UL;
+	psInitStream->ui32RPtr = 0;
+	psInitStream->ui32WPtr = 0;
+	psInitStream->ui32DataWritten = 0;
+	psInitStream->ui32CapMode = ui32CapMode;
+	psInitStream->ui32OutMode = ui32OutMode;
+	psInitStream->ui32DebugLevel = DEBUG_LEVEL_0;
+	psInitStream->ui32DefaultMode = ui32CapMode;
+	psInitStream->ui32Start = 0;
+	psInitStream->ui32End = 0;
+	psInitStream->ui32Current = 0;
+	psInitStream->ui32SampleRate = 1;
+	psInitStream->ui32Access = 0;
+	psInitStream->ui32Timeout = 0;
+	psInitStream->ui32Marker = 0;
+	psInitStream->bInitPhaseComplete = IMG_FALSE;
+
+	psStream->psInitStream = psInitStream;
+
+
+	psLFBuffer->psStream = psStream;
+	psLFBuffer->ui32BufLen = 0UL;
+
+	g_bHotkeyMiddump = IMG_FALSE;
+	g_ui32HotkeyMiddumpStart = 0xffffffffUL;
+	g_ui32HotkeyMiddumpEnd = 0xffffffffUL;
+
+
+
+	ui32Off = 0;
+
+	do
+	{
+		psStream->szName[ui32Off] = pszName[ui32Off];
+
+		ui32Off++;
+	}
+	while ((pszName[ui32Off] != 0) && (ui32Off < (4096UL - sizeof(DBG_STREAM))));
+
+	psStream->szName[ui32Off] = pszName[ui32Off];
+
+
+
+	psStream->psNext = g_psStreamList;
+	g_psStreamList = psStream;
+
+	psLFBuffer->psNext = g_psLFBufferList;
+	g_psLFBufferList = psLFBuffer;
+
+
+	return((IMG_VOID *) psStream);
+}
+
+void IMG_CALLCONV DBGDrivDestroyStream(PDBG_STREAM psStream)
+{
+	PDBG_STREAM	psStreamThis;
+	PDBG_STREAM	psStreamPrev;
+	PDBG_LASTFRAME_BUFFER	psLFBuffer;
+	PDBG_LASTFRAME_BUFFER	psLFThis;
+	PDBG_LASTFRAME_BUFFER	psLFPrev;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "DBGDriv: Destroying stream %s\r\n", psStream->szName ));
+
+
+
+	if (!StreamValid(psStream))
+	{
+		return;
+	}
+
+	psLFBuffer = FindLFBuf(psStream);
+
+
+
+	psStreamThis = g_psStreamList;
+	psStreamPrev = 0;
+
+	while (psStreamThis)
+	{
+		if (psStreamThis == psStream)
+		{
+			if (psStreamPrev)
+			{
+				psStreamPrev->psNext = psStreamThis->psNext;
+			}
+			else
+			{
+				g_psStreamList = psStreamThis->psNext;
+			}
+
+			psStreamThis = 0;
+		}
+		else
+		{
+			psStreamPrev = psStreamThis;
+			psStreamThis = psStreamThis->psNext;
+		}
+	}
+
+	psLFThis = g_psLFBufferList;
+	psLFPrev = 0;
+
+	while (psLFThis)
+	{
+		if (psLFThis == psLFBuffer)
+		{
+			if (psLFPrev)
+			{
+				psLFPrev->psNext = psLFThis->psNext;
+			}
+			else
+			{
+				g_psLFBufferList = psLFThis->psNext;
+			}
+
+			psLFThis = 0;
+		}
+		else
+		{
+			psLFPrev = psLFThis;
+			psLFThis = psLFThis->psNext;
+		}
+	}
+
+
+	if (psStream->ui32CapMode & DEBUG_CAPMODE_HOTKEY)
+	{
+		DeactivateHotKeys();
+	}
+
+
+
+	if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+	{
+		HostNonPageablePageFree((IMG_VOID *)psStream->ui32Base);
+		HostNonPageablePageFree((IMG_VOID *)psStream->psInitStream->ui32Base);
+	}
+	else
+	{
+		HostPageablePageFree((IMG_VOID *)psStream->ui32Base);
+		HostPageablePageFree((IMG_VOID *)psStream->psInitStream->ui32Base);
+	}
+
+	HostNonPageablePageFree(psStream->psInitStream);
+	HostNonPageablePageFree(psStream);
+	HostNonPageablePageFree(psLFBuffer);
+
+	if (g_psStreamList == 0)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Stream list now empty" ));
+	}
+
+	return;
+}
+
+IMG_VOID * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
+{
+	PDBG_STREAM	psStream;
+	PDBG_STREAM	psThis;
+	IMG_UINT32	ui32Off;
+	IMG_BOOL	bAreSame;
+
+	psStream = 0;
+
+
+
+	for (psThis = g_psStreamList; psThis != IMG_NULL; psThis = psThis->psNext)
+	{
+		bAreSame = IMG_TRUE;
+		ui32Off = 0;
+
+		if (strlen(psThis->szName) == strlen(pszName))
+		{
+			while ((psThis->szName[ui32Off] != 0) && (pszName[ui32Off] != 0) && (ui32Off < 128) && bAreSame)
+			{
+				if (psThis->szName[ui32Off] != pszName[ui32Off])
+				{
+					bAreSame = IMG_FALSE;
+				}
+
+				ui32Off++;
+			}
+		}
+		else
+		{
+			bAreSame = IMG_FALSE;
+		}
+
+		if (bAreSame)
+		{
+			psStream = psThis;
+			break;
+		}
+	}
+
+	if(bResetStream && psStream)
+	{
+		static IMG_CHAR szComment[] = "-- Init phase terminated\r\n";
+		psStream->psInitStream->ui32RPtr = 0;
+		psStream->ui32RPtr = 0;
+		psStream->ui32WPtr = 0;
+		psStream->ui32DataWritten = psStream->psInitStream->ui32DataWritten;
+		if (psStream->bInitPhaseComplete == IMG_FALSE)
+		{
+			if (psStream->ui32Flags & DEBUG_FLAGS_TEXTSTREAM)
+			{
+				DBGDrivWrite2(psStream, (IMG_UINT8 *)szComment, sizeof(szComment) - 1, 0x01);
+			}
+			psStream->bInitPhaseComplete = IMG_TRUE;
+		}
+	}
+
+	return((IMG_VOID *) psStream);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+
+
+	if (!StreamValid(psStream))
+	{
+		return(0xFFFFFFFFUL);
+	}
+
+
+
+	if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+	{
+		if	((psStream->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+		{
+			return(0);
+		}
+	}
+	else
+	{
+		if (psStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+		{
+			if ((psStream->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+			{
+				return(0);
+			}
+		}
+	}
+
+	return(DBGDrivWriteString(psStream,pszString,ui32Level));
+
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+	IMG_UINT32	ui32Len;
+	IMG_UINT32	ui32Space;
+	IMG_UINT32	ui32WPtr;
+	IMG_UINT8 *	pui8Buffer;
+
+
+
+	if (!StreamValid(psStream))
+	{
+		return(0xFFFFFFFFUL);
+	}
+
+
+
+	if ((psStream->ui32DebugLevel & ui32Level) == 0)
+	{
+		return(0xFFFFFFFFUL);
+	}
+
+
+
+
+	if ((psStream->ui32OutMode & DEBUG_OUTMODE_ASYNC) == 0)
+	{
+		if (psStream->ui32OutMode & DEBUG_OUTMODE_STANDARDDBG)
+		{
+			PVR_DPF((PVR_DBG_MESSAGE,"%s: %s\r\n",psStream->szName, pszString));
+		}
+
+
+
+		if (psStream->ui32OutMode & DEBUG_OUTMODE_MONO)
+		{
+			MonoOut(psStream->szName,IMG_FALSE);
+			MonoOut(": ",IMG_FALSE);
+			MonoOut(pszString,IMG_TRUE);
+		}
+	}
+
+
+
+	if	(
+			!(
+				((psStream->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) != 0) ||
+				((psStream->ui32OutMode & DEBUG_OUTMODE_ASYNC) != 0)
+			)
+		)
+	{
+		return(0xFFFFFFFFUL);
+	}
+
+
+
+	ui32Space=SpaceInStream(psStream);
+
+	if(ui32Space > 0)
+	{
+		ui32Space--;
+	}
+
+	ui32Len		= 0;
+	ui32WPtr	= psStream->ui32WPtr;
+	pui8Buffer	= (IMG_UINT8 *) psStream->ui32Base;
+
+	while((pszString[ui32Len] != 0) && (ui32Len < ui32Space))
+	{
+		pui8Buffer[ui32WPtr] = (IMG_UINT8)pszString[ui32Len];
+		ui32Len++;
+		ui32WPtr++;
+		if (ui32WPtr == psStream->ui32Size)
+		{
+			ui32WPtr = 0;
+		}
+	}
+
+	if (ui32Len < ui32Space)
+	{
+
+		pui8Buffer[ui32WPtr] = (IMG_UINT8)pszString[ui32Len];
+		ui32Len++;
+		ui32WPtr++;
+		if (ui32WPtr == psStream->ui32Size)
+		{
+			ui32WPtr = 0;
+		}
+
+
+		psStream->ui32WPtr = ui32WPtr;
+		psStream->ui32DataWritten+= ui32Len;
+	} else
+	{
+		ui32Len = 0;
+	}
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+	if (ui32Len)
+	{
+		HostSignalEvent(DBG_EVENT_STREAM_DATA);
+	}
+#endif
+
+	return(ui32Len);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit)
+{
+	IMG_UINT32				ui32OutLen;
+	IMG_UINT32				ui32Len;
+	IMG_UINT32				ui32Offset;
+	IMG_UINT8				*pui8Buff;
+
+
+
+	if (!StreamValid(psStream))
+	{
+		return(0);
+	}
+
+
+
+	pui8Buff = (IMG_UINT8 *) psStream->ui32Base;
+	ui32Offset = psStream->ui32RPtr;
+
+	if (psStream->ui32RPtr == psStream->ui32WPtr)
+	{
+		return(0);
+	}
+
+
+
+	ui32Len = 0;
+	while((pui8Buff[ui32Offset] != 0) && (ui32Offset != psStream->ui32WPtr))
+	{
+		ui32Offset++;
+		ui32Len++;
+
+
+
+		if (ui32Offset == psStream->ui32Size)
+		{
+			ui32Offset = 0;
+		}
+	}
+
+	ui32OutLen = ui32Len + 1;
+
+
+
+	if (ui32Len > ui32Limit)
+	{
+		return(0);
+	}
+
+
+
+	ui32Offset = psStream->ui32RPtr;
+	ui32Len = 0;
+
+	while ((pui8Buff[ui32Offset] != 0) && (ui32Len < ui32Limit))
+	{
+		pszString[ui32Len] = (IMG_CHAR)pui8Buff[ui32Offset];
+		ui32Offset++;
+		ui32Len++;
+
+
+
+		if (ui32Offset == psStream->ui32Size)
+		{
+			ui32Offset = 0;
+		}
+	}
+
+	pszString[ui32Len] = (IMG_CHAR)pui8Buff[ui32Offset];
+
+	psStream->ui32RPtr = ui32Offset + 1;
+
+	if (psStream->ui32RPtr == psStream->ui32Size)
+	{
+		psStream->ui32RPtr = 0;
+	}
+
+	return(ui32OutLen);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+	IMG_UINT32				ui32Space;
+	DBG_STREAM *psStream;
+
+
+
+	if (!StreamValid(psMainStream))
+	{
+		return(0xFFFFFFFFUL);
+	}
+
+
+
+	if ((psMainStream->ui32DebugLevel & ui32Level) == 0)
+	{
+		return(0xFFFFFFFFUL);
+	}
+
+
+
+	if (psMainStream->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+	{
+		if	((psMainStream->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+		{
+			return(0xFFFFFFFFUL);
+		}
+	}
+	else if (psMainStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+	{
+		if ((psMainStream->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+			return(0xFFFFFFFFUL);
+	}
+
+	if(psMainStream->bInitPhaseComplete)
+	{
+		psStream = psMainStream;
+	}
+	else
+	{
+		psStream = psMainStream->psInitStream;
+	}
+
+
+
+	ui32Space=SpaceInStream(psStream);
+
+
+
+	if ((psStream->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) == 0)
+	{
+		return(0);
+	}
+
+	if (ui32Space < 8)
+	{
+		return(0);
+	}
+
+
+
+	if (ui32Space <= (ui32InBuffSize + 4))
+	{
+		ui32InBuffSize = ui32Space - 8;
+	}
+
+
+
+	Write(psStream,(IMG_UINT8 *) &ui32InBuffSize,4);
+	Write(psStream,pui8InBuf,ui32InBuffSize);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+	if (ui32InBuffSize)
+	{
+		HostSignalEvent(DBG_EVENT_STREAM_DATA);
+	}
+#endif
+	return(ui32InBuffSize);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+
+
+	if (!StreamValid(psStream))
+	{
+		return(0xFFFFFFFFUL);
+	}
+
+
+
+	if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+	{
+		if	((psStream->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+		{
+			return(0xFFFFFFFFUL);
+		}
+	}
+	else
+	{
+		if (psStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+		{
+			if ((psStream->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+			{
+				return(0xFFFFFFFFUL);
+			}
+		}
+	}
+
+	return(DBGDrivWrite2(psStream,pui8InBuf,ui32InBuffSize,ui32Level));
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+	IMG_UINT32	ui32Space;
+	DBG_STREAM	*psStream;
+
+
+
+	if (!StreamValid(psMainStream))
+	{
+		return(0xFFFFFFFFUL);
+	}
+
+
+
+	if ((psMainStream->ui32DebugLevel & ui32Level) == 0)
+	{
+		return(0xFFFFFFFFUL);
+	}
+
+	if(psMainStream->bInitPhaseComplete)
+	{
+		psStream = psMainStream;
+	}
+	else
+	{
+		psStream = psMainStream->psInitStream;
+	}
+
+
+
+	ui32Space=SpaceInStream(psStream);
+
+
+
+	if ((psStream->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) == 0)
+	{
+		return(0);
+	}
+
+
+
+	if (psStream->ui32Flags & DEBUG_FLAGS_NO_BUF_EXPANDSION)
+	{
+
+
+
+		if (ui32Space < 32)
+		{
+			return(0);
+		}
+	}
+	else
+	{
+		if ((ui32Space < 32) || (ui32Space <= (ui32InBuffSize + 4)))
+		{
+			IMG_UINT32	ui32NewBufSize;
+
+
+
+			ui32NewBufSize = 2 * psStream->ui32Size;
+
+			if (ui32InBuffSize > psStream->ui32Size)
+			{
+				ui32NewBufSize += ui32InBuffSize;
+			}
+
+
+
+			if (!ExpandStreamBuffer(psStream,ui32NewBufSize))
+			{
+				if (ui32Space < 32)
+				{
+					return(0);
+				}
+			}
+
+
+
+			ui32Space = SpaceInStream(psStream);
+		}
+	}
+
+
+
+	if (ui32Space <= (ui32InBuffSize + 4))
+	{
+		ui32InBuffSize = ui32Space - 4;
+	}
+
+
+
+	Write(psStream,pui8InBuf,ui32InBuffSize);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+	if (ui32InBuffSize)
+	{
+		HostSignalEvent(DBG_EVENT_STREAM_DATA);
+	}
+#endif
+	return(ui32InBuffSize);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psMainStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
+{
+	IMG_UINT32 ui32Data;
+	DBG_STREAM *psStream;
+
+
+
+	if (!StreamValid(psMainStream))
+	{
+		return(0);
+	}
+
+	if(bReadInitBuffer)
+	{
+		psStream = psMainStream->psInitStream;
+	}
+	else
+	{
+		psStream = psMainStream;
+	}
+
+	if (psStream->ui32RPtr == psStream->ui32WPtr)
+	{
+		return(0);
+	}
+
+
+
+	if (psStream->ui32RPtr <= psStream->ui32WPtr)
+	{
+		ui32Data = psStream->ui32WPtr - psStream->ui32RPtr;
+	}
+	else
+	{
+		ui32Data = psStream->ui32WPtr + (psStream->ui32Size - psStream->ui32RPtr);
+	}
+
+
+
+	if (ui32Data > ui32OutBuffSize)
+	{
+		ui32Data = ui32OutBuffSize;
+	}
+
+
+
+	if ((psStream->ui32RPtr + ui32Data) > psStream->ui32Size)
+	{
+		IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32RPtr;
+		IMG_UINT32 ui32B2 = ui32Data - ui32B1;
+
+
+		HostMemCopy((IMG_VOID *) pui8OutBuf,
+				(IMG_VOID *)(psStream->ui32Base + psStream->ui32RPtr),
+				ui32B1);
+
+
+		HostMemCopy((IMG_VOID *)((IMG_UINT32) pui8OutBuf + ui32B1),
+				(IMG_VOID *)psStream->ui32Base,
+				ui32B2);
+
+
+		psStream->ui32RPtr = ui32B2;
+	}
+	else
+	{
+		HostMemCopy((IMG_VOID *) pui8OutBuf,
+				(IMG_VOID *)(psStream->ui32Base + psStream->ui32RPtr),
+				ui32Data);
+
+
+		psStream->ui32RPtr += ui32Data;
+
+
+		if (psStream->ui32RPtr == psStream->ui32Size)
+		{
+			psStream->ui32RPtr = 0;
+		}
+	}
+
+	return(ui32Data);
+}
+
+void IMG_CALLCONV DBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate)
+{
+
+
+	if (!StreamValid(psStream))
+	{
+		return;
+	}
+
+	psStream->ui32CapMode = ui32Mode;
+	psStream->ui32DefaultMode = ui32Mode;
+	psStream->ui32Start = ui32Start;
+	psStream->ui32End = ui32End;
+	psStream->ui32SampleRate = ui32SampleRate;
+
+
+
+	if (psStream->ui32CapMode & DEBUG_CAPMODE_HOTKEY)
+	{
+		ActivateHotKeys(psStream);
+	}
+}
+
+void IMG_CALLCONV DBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode)
+{
+
+
+	if (!StreamValid(psStream))
+	{
+		return;
+	}
+
+	psStream->ui32OutMode = ui32OutMode;
+}
+
+void IMG_CALLCONV DBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel)
+{
+
+
+	if (!StreamValid(psStream))
+	{
+		return;
+	}
+
+	psStream->ui32DebugLevel = ui32DebugLevel;
+}
+
+void IMG_CALLCONV DBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame)
+{
+
+
+	if (!StreamValid(psStream))
+	{
+		return;
+	}
+
+	psStream->ui32Current = ui32Frame;
+
+	if ((ui32Frame >= psStream->ui32Start) &&
+		(ui32Frame <= psStream->ui32End) &&
+		(((ui32Frame - psStream->ui32Start) % psStream->ui32SampleRate) == 0))
+	{
+		psStream->ui32Flags |= DEBUG_FLAGS_ENABLESAMPLE;
+	}
+	else
+	{
+		psStream->ui32Flags &= ~DEBUG_FLAGS_ENABLESAMPLE;
+	}
+
+	if (g_bHotkeyMiddump)
+	{
+		if ((ui32Frame >= g_ui32HotkeyMiddumpStart) &&
+			(ui32Frame <= g_ui32HotkeyMiddumpEnd) &&
+			(((ui32Frame - g_ui32HotkeyMiddumpStart) % psStream->ui32SampleRate) == 0))
+		{
+			psStream->ui32Flags |= DEBUG_FLAGS_ENABLESAMPLE;
+		}
+		else
+		{
+			psStream->ui32Flags &= ~DEBUG_FLAGS_ENABLESAMPLE;
+			if (psStream->ui32Current > g_ui32HotkeyMiddumpEnd)
+			{
+				g_bHotkeyMiddump = IMG_FALSE;
+			}
+		}
+	}
+
+
+	if (g_bHotKeyRegistered)
+	{
+		g_bHotKeyRegistered = IMG_FALSE;
+
+		PVR_DPF((PVR_DBG_MESSAGE,"Hotkey pressed (%08x)!\n",psStream));
+
+		if (!g_bHotKeyPressed)
+		{
+
+
+			g_ui32HotKeyFrame = psStream->ui32Current + 2;
+
+
+
+			g_bHotKeyPressed = IMG_TRUE;
+		}
+
+
+
+		if (((psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
+			((psStream->ui32CapMode & DEBUG_CAPMODE_HOTKEY) != 0))
+		{
+			if (!g_bHotkeyMiddump)
+			{
+
+				g_ui32HotkeyMiddumpStart = g_ui32HotKeyFrame + 1;
+				g_ui32HotkeyMiddumpEnd = 0xffffffff;
+				g_bHotkeyMiddump = IMG_TRUE;
+				PVR_DPF((PVR_DBG_MESSAGE,"Sampling every %d frame(s)\n", psStream->ui32SampleRate));
+			}
+			else
+			{
+
+				g_ui32HotkeyMiddumpEnd = g_ui32HotKeyFrame;
+				PVR_DPF((PVR_DBG_MESSAGE,"Turning off sampling\n"));
+			}
+		}
+
+	}
+
+
+
+	if (psStream->ui32Current > g_ui32HotKeyFrame)
+	{
+		g_bHotKeyPressed = IMG_FALSE;
+	}
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(PDBG_STREAM psStream)
+{
+
+
+	if (!StreamValid(psStream))
+	{
+		return(0);
+	}
+
+	return(psStream->ui32Current);
+}
+
+IMG_BOOL IMG_CALLCONV DBGDrivIsLastCaptureFrame(PDBG_STREAM psStream)
+{
+	IMG_UINT32	ui32NextFrame;
+
+
+
+	if (!StreamValid(psStream))
+	{
+		return IMG_FALSE;
+	}
+
+	if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+	{
+		ui32NextFrame = psStream->ui32Current + psStream->ui32SampleRate;
+		if (ui32NextFrame > psStream->ui32End)
+		{
+			return IMG_TRUE;
+		}
+	}
+	return IMG_FALSE;
+}
+
+IMG_BOOL IMG_CALLCONV DBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame)
+{
+	IMG_UINT32 ui32FrameShift = bCheckPreviousFrame ? 1UL : 0UL;
+
+
+
+	if (!StreamValid(psStream))
+	{
+		return IMG_FALSE;
+	}
+
+	if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+	{
+
+		if (g_bHotkeyMiddump)
+		{
+			if ((psStream->ui32Current >= (g_ui32HotkeyMiddumpStart - ui32FrameShift)) &&
+				(psStream->ui32Current <= (g_ui32HotkeyMiddumpEnd - ui32FrameShift)) &&
+				((((psStream->ui32Current + ui32FrameShift) - g_ui32HotkeyMiddumpStart) % psStream->ui32SampleRate) == 0))
+			{
+				return IMG_TRUE;
+			}
+		}
+		else
+		{
+			if ((psStream->ui32Current >= (psStream->ui32Start - ui32FrameShift)) &&
+				(psStream->ui32Current <= (psStream->ui32End - ui32FrameShift)) &&
+				((((psStream->ui32Current + ui32FrameShift) - psStream->ui32Start) % psStream->ui32SampleRate) == 0))
+			{
+				return IMG_TRUE;
+			}
+		}
+	}
+	else if (psStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+	{
+		if ((psStream->ui32Current == (g_ui32HotKeyFrame-ui32FrameShift)) && (g_bHotKeyPressed))
+		{
+			return IMG_TRUE;
+		}
+	}
+	return IMG_FALSE;
+}
+
+void IMG_CALLCONV DBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode)
+{
+
+
+	if (!StreamValid(psStream))
+	{
+		return;
+	}
+
+	psStream->ui32CapMode = ui32Mode;
+}
+
+void IMG_CALLCONV DBGDrivDefaultMode(PDBG_STREAM psStream)
+{
+
+
+	if (!StreamValid(psStream))
+	{
+		return;
+	}
+
+	psStream->ui32CapMode = psStream->ui32DefaultMode;
+}
+
+void IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+
+
+	if (!StreamValid(psStream))
+	{
+		return;
+	}
+
+	psStream->ui32Marker = ui32Marker;
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream)
+{
+
+
+	if (!StreamValid(psStream))
+	{
+		return 0;
+	}
+
+	return psStream->ui32Marker;
+}
+
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetStreamOffset(PDBG_STREAM psMainStream)
+{
+	PDBG_STREAM psStream;
+
+
+
+	if (!StreamValid(psMainStream))
+	{
+		return 0;
+	}
+
+	if(psMainStream->bInitPhaseComplete)
+	{
+		psStream = psMainStream;
+	}
+	else
+	{
+		psStream = psMainStream->psInitStream;
+	}
+
+	return psStream->ui32DataWritten;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivSetStreamOffset(PDBG_STREAM psMainStream, IMG_UINT32 ui32StreamOffset)
+{
+	PDBG_STREAM psStream;
+
+
+
+	if (!StreamValid(psMainStream))
+	{
+		return;
+	}
+
+	if(psMainStream->bInitPhaseComplete)
+	{
+		psStream = psMainStream;
+	}
+	else
+	{
+		psStream = psMainStream->psInitStream;
+	}
+
+	psStream->ui32DataWritten = ui32StreamOffset;
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetServiceTable(void)
+{
+	return((IMG_UINT32) &g_sDBGKMServices);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 * pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags)
+{
+	PDBG_LASTFRAME_BUFFER	psLFBuffer;
+
+
+
+	if (!StreamValid(psStream))
+	{
+		return(0xFFFFFFFFUL);
+	}
+
+
+
+	if ((psStream->ui32DebugLevel & ui32Level) == 0)
+	{
+		return(0xFFFFFFFFUL);
+	}
+
+
+
+	if ((psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0)
+	{
+		if	((psStream->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+		{
+			return(0xFFFFFFFFUL);
+		}
+	}
+	else if (psStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+	{
+		if ((psStream->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+			return(0xFFFFFFFFUL);
+	}
+
+	psLFBuffer = FindLFBuf(psStream);
+
+	if (ui32Flags & WRITELF_FLAGS_RESETBUF)
+	{
+
+
+		ui32InBuffSize = (ui32InBuffSize > LAST_FRAME_BUF_SIZE) ? LAST_FRAME_BUF_SIZE : ui32InBuffSize;
+		HostMemCopy((IMG_VOID *)psLFBuffer->ui8Buffer, (IMG_VOID *)pui8InBuf, ui32InBuffSize);
+		psLFBuffer->ui32BufLen = ui32InBuffSize;
+	}
+	else
+	{
+
+
+		ui32InBuffSize = ((psLFBuffer->ui32BufLen + ui32InBuffSize) > LAST_FRAME_BUF_SIZE) ? (LAST_FRAME_BUF_SIZE - psLFBuffer->ui32BufLen) : ui32InBuffSize;
+		HostMemCopy((IMG_VOID *)(&psLFBuffer->ui8Buffer[psLFBuffer->ui32BufLen]), (IMG_VOID *)pui8InBuf, ui32InBuffSize);
+		psLFBuffer->ui32BufLen += ui32InBuffSize;
+	}
+
+	return(ui32InBuffSize);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 * pui8OutBuf)
+{
+	PDBG_LASTFRAME_BUFFER	psLFBuffer;
+	IMG_UINT32	ui32Data;
+
+
+
+	if (!StreamValid(psStream))
+	{
+		return(0);
+	}
+
+	psLFBuffer = FindLFBuf(psStream);
+
+
+
+	ui32Data = (ui32OutBuffSize < psLFBuffer->ui32BufLen) ? ui32OutBuffSize : psLFBuffer->ui32BufLen;
+
+
+
+	HostMemCopy((IMG_VOID *)pui8OutBuf, (IMG_VOID *)psLFBuffer->ui8Buffer, ui32Data);
+
+	return ui32Data;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivStartInitPhase(PDBG_STREAM psStream)
+{
+	psStream->bInitPhaseComplete = IMG_FALSE;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivStopInitPhase(PDBG_STREAM psStream)
+{
+	psStream->bInitPhaseComplete = IMG_TRUE;
+}
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+IMG_VOID IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent)
+{
+	HostWaitForEvent(eEvent);
+}
+#endif
+
+IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize)
+{
+	IMG_VOID *	pvNewBuf;
+	IMG_UINT32	ui32NewSizeInPages;
+	IMG_UINT32	ui32NewWOffset;
+	IMG_UINT32	ui32SpaceInOldBuf;
+
+
+
+	if (psStream->ui32Size >= ui32NewSize)
+	{
+		return IMG_FALSE;
+	}
+
+
+
+	ui32SpaceInOldBuf = SpaceInStream(psStream);
+
+
+
+	ui32NewSizeInPages = ((ui32NewSize + 0xfffUL) & ~0xfffUL) / 4096UL;
+
+	if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+	{
+		pvNewBuf = HostNonPageablePageAlloc(ui32NewSizeInPages);
+	}
+	else
+	{
+		pvNewBuf = HostPageablePageAlloc(ui32NewSizeInPages);
+	}
+
+	if (pvNewBuf == IMG_NULL)
+	{
+		return IMG_FALSE;
+	}
+
+
+
+
+	if (psStream->ui32RPtr <= psStream->ui32WPtr)
+	{
+
+
+		HostMemCopy((IMG_VOID *)pvNewBuf, (IMG_VOID *)(psStream->ui32Base + psStream->ui32RPtr), psStream->ui32WPtr - psStream->ui32RPtr);
+	}
+	else
+	{
+		IMG_UINT32	ui32FirstCopySize;
+
+
+
+		ui32FirstCopySize = psStream->ui32Size - psStream->ui32RPtr;
+
+		HostMemCopy((IMG_VOID *)pvNewBuf, (IMG_VOID *)(psStream->ui32Base + psStream->ui32RPtr), ui32FirstCopySize);
+
+
+
+		HostMemCopy((IMG_VOID *)((IMG_UINT32)pvNewBuf + ui32FirstCopySize), (IMG_VOID *)psStream->ui32Base, psStream->ui32WPtr);
+	}
+
+
+
+	ui32NewWOffset = psStream->ui32Size - ui32SpaceInOldBuf;
+
+
+
+	if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+	{
+		HostNonPageablePageFree((IMG_VOID *)psStream->ui32Base);
+	}
+	else
+	{
+		HostPageablePageFree((IMG_VOID *)psStream->ui32Base);
+	}
+
+
+
+	psStream->ui32Base = (IMG_UINT32)pvNewBuf;
+	psStream->ui32RPtr = 0;
+	psStream->ui32WPtr = ui32NewWOffset;
+	psStream->ui32Size = ui32NewSizeInPages * 4096;
+
+	return IMG_TRUE;
+}
+
+IMG_UINT32 SpaceInStream(PDBG_STREAM psStream)
+{
+	IMG_UINT32	ui32Space;
+
+	if (psStream->ui32RPtr > psStream->ui32WPtr)
+	{
+		ui32Space = psStream->ui32RPtr - psStream->ui32WPtr;
+	}
+	else
+	{
+		ui32Space = psStream->ui32RPtr + (psStream->ui32Size - psStream->ui32WPtr);
+	}
+
+	return ui32Space;
+}
+
+
+void DestroyAllStreams(void)
+{
+	while (g_psStreamList != IMG_NULL)
+	{
+		DBGDrivDestroyStream(g_psStreamList);
+	}
+	return;
+}
+
+PDBG_LASTFRAME_BUFFER FindLFBuf(PDBG_STREAM psStream)
+{
+	PDBG_LASTFRAME_BUFFER	psLFBuffer;
+
+	psLFBuffer = g_psLFBufferList;
+
+	while (psLFBuffer)
+	{
+		if (psLFBuffer->psStream == psStream)
+		{
+			break;
+		}
+
+		psLFBuffer = psLFBuffer->psNext;
+	}
+
+	return psLFBuffer;
+}
+
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.h b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.h
new file mode 100644
index 0000000..167e0f6
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/dbgdriv.h
@@ -0,0 +1,112 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _DBGDRIV_
+#define _DBGDRIV_
+
+#define BUFFER_SIZE 64*PAGESIZE
+
+#define DBGDRIV_VERSION 	0x100
+#define MAX_PROCESSES 		2
+#define BLOCK_USED			0x01
+#define BLOCK_LOCKED		0x02
+#define DBGDRIV_MONOBASE	0x000B0000
+
+
+extern IMG_VOID *	g_pvAPIMutex;
+
+IMG_VOID * IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR *		pszName,
+								   IMG_UINT32 	ui32CapMode,
+								   IMG_UINT32 	ui32OutMode,
+								   IMG_UINT32	ui32Flags,
+								   IMG_UINT32 	ui32Pages);
+IMG_VOID   IMG_CALLCONV DBGDrivDestroyStream(PDBG_STREAM psStream);
+IMG_VOID * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit);
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBufferSize,IMG_UINT8 *pui8OutBuf);
+IMG_VOID   IMG_CALLCONV DBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32Stop,IMG_UINT32 ui32SampleRate);
+IMG_VOID   IMG_CALLCONV DBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode);
+IMG_VOID   IMG_CALLCONV DBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel);
+IMG_VOID   IMG_CALLCONV DBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(PDBG_STREAM psStream);
+IMG_VOID   IMG_CALLCONV DBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode);
+IMG_VOID   IMG_CALLCONV DBGDrivDefaultMode(PDBG_STREAM psStream);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetServiceTable(IMG_VOID);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_VOID   IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream);
+IMG_BOOL   IMG_CALLCONV DBGDrivIsLastCaptureFrame(PDBG_STREAM psStream);
+IMG_BOOL   IMG_CALLCONV DBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags);
+IMG_UINT32 IMG_CALLCONV DBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 *pui8OutBuf);
+IMG_VOID   IMG_CALLCONV DBGDrivStartInitPhase(PDBG_STREAM psStream);
+IMG_VOID   IMG_CALLCONV DBGDrivStopInitPhase(PDBG_STREAM psStream);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetStreamOffset(PDBG_STREAM psStream);
+IMG_VOID   IMG_CALLCONV DBGDrivSetStreamOffset(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset);
+IMG_VOID   IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent);
+
+IMG_VOID DestroyAllStreams(IMG_VOID);
+
+IMG_UINT32 AtoI(IMG_CHAR *szIn);
+
+IMG_VOID HostMemSet(IMG_VOID *pvDest,IMG_UINT8 ui8Value,IMG_UINT32 ui32Size);
+IMG_VOID HostMemCopy(IMG_VOID *pvDest,IMG_VOID *pvSrc,IMG_UINT32 ui32Size);
+IMG_BOOL StreamValid(PDBG_STREAM psStream);
+IMG_VOID Write(PDBG_STREAM psStream,IMG_UINT8 *pui8Data,IMG_UINT32 ui32InBuffSize);
+IMG_VOID MonoOut(IMG_CHAR * pszString,IMG_BOOL bNewLine);
+
+
+IMG_VOID * IMG_CALLCONV ExtDBGDrivCreateStream(IMG_CHAR *	pszName, IMG_UINT32 ui32CapMode, IMG_UINT32	ui32OutMode, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivDestroyStream(PDBG_STREAM psStream);
+IMG_VOID * IMG_CALLCONV ExtDBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivRead(PDBG_STREAM psStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 *pui8OutBuf);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetFrame(PDBG_STREAM psStream);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivDefaultMode(PDBG_STREAM psStream);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetMarker(PDBG_STREAM psStream);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivStartInitPhase(PDBG_STREAM psStream);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivStopInitPhase(PDBG_STREAM psStream);
+IMG_BOOL   IMG_CALLCONV ExtDBGDrivIsLastCaptureFrame(PDBG_STREAM psStream);
+IMG_BOOL   IMG_CALLCONV ExtDBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 *pui8OutBuf);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetStreamOffset(PDBG_STREAM psStream);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivSetStreamOffset(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset);
+IMG_VOID   IMG_CALLCONV ExtDBGDrivWaitForEvent(DBG_EVENT eEvent);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hostfunc.h b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hostfunc.h
new file mode 100644
index 0000000..558d6fa
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hostfunc.h
@@ -0,0 +1,54 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _HOSTFUNC_
+#define _HOSTFUNC_
+
+#define HOST_PAGESIZE			(4096)
+#define DBG_MEMORY_INITIALIZER	(0xe2)
+
+IMG_UINT32 HostReadRegistryDWORDFromString(IMG_CHAR *pcKey, IMG_CHAR *pcValueName, IMG_UINT32 *pui32Data);
+
+IMG_VOID * HostPageablePageAlloc(IMG_UINT32 ui32Pages);
+IMG_VOID HostPageablePageFree(IMG_VOID * pvBase);
+IMG_VOID * HostNonPageablePageAlloc(IMG_UINT32 ui32Pages);
+IMG_VOID HostNonPageablePageFree(IMG_VOID * pvBase);
+
+IMG_VOID * HostMapKrnBufIntoUser(IMG_VOID * pvKrnAddr, IMG_UINT32 ui32Size, IMG_VOID * *ppvMdl);
+IMG_VOID HostUnMapKrnBufFromUser(IMG_VOID * pvUserAddr, IMG_VOID * pvMdl, IMG_VOID * pvProcess);
+
+IMG_VOID HostCreateRegDeclStreams(IMG_VOID);
+
+IMG_VOID * HostCreateMutex(IMG_VOID);
+IMG_VOID HostAquireMutex(IMG_VOID * pvMutex);
+IMG_VOID HostReleaseMutex(IMG_VOID * pvMutex);
+IMG_VOID HostDestroyMutex(IMG_VOID * pvMutex);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+IMG_INT32 HostCreateEventObjects(IMG_VOID);
+IMG_VOID HostWaitForEvent(DBG_EVENT eEvent);
+IMG_VOID HostSignalEvent(DBG_EVENT eEvent);
+IMG_VOID HostDestroyEventObjects(IMG_VOID);
+#endif
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hotkey.c b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hotkey.c
new file mode 100644
index 0000000..7ea2b5a
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hotkey.c
@@ -0,0 +1,131 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+
+#if !defined(LINUX)
+#include <ntddk.h>
+#include <windef.h>
+#endif
+
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+#include "hostfunc.h"
+
+
+
+
+
+IMG_UINT32	g_ui32HotKeyFrame = 0xFFFFFFFF;
+IMG_BOOL	g_bHotKeyPressed = IMG_FALSE;
+IMG_BOOL	g_bHotKeyRegistered = IMG_FALSE;
+
+PRIVATEHOTKEYDATA    g_PrivateHotKeyData;
+
+
+IMG_VOID ReadInHotKeys(IMG_VOID)
+{
+	g_PrivateHotKeyData.ui32ScanCode = 0x58;
+	g_PrivateHotKeyData.ui32ShiftState = 0x0;
+
+
+
+#if 0
+	if (_RegOpenKey(HKEY_LOCAL_MACHINE,pszRegPath,&hKey) == ERROR_SUCCESS)
+	{
+
+
+		QueryReg(hKey,"ui32ScanCode",&g_PrivateHotKeyData.ui32ScanCode);
+		QueryReg(hKey,"ui32ShiftState",&g_PrivateHotKeyData.ui32ShiftState);
+	}
+#else
+	HostReadRegistryDWORDFromString("DEBUG\\Streams", "ui32ScanCode"  , &g_PrivateHotKeyData.ui32ScanCode);
+	HostReadRegistryDWORDFromString("DEBUG\\Streams", "ui32ShiftState", &g_PrivateHotKeyData.ui32ShiftState);
+#endif
+}
+
+IMG_VOID RegisterKeyPressed(IMG_UINT32 dwui32ScanCode, PHOTKEYINFO pInfo)
+{
+	PDBG_STREAM	psStream;
+
+	PVR_UNREFERENCED_PARAMETER(pInfo);
+
+	if (dwui32ScanCode == g_PrivateHotKeyData.ui32ScanCode)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE,"PDUMP Hotkey pressed !\n"));
+
+		psStream = (PDBG_STREAM) g_PrivateHotKeyData.sHotKeyInfo.pvStream;
+
+		if (!g_bHotKeyPressed)
+		{
+
+
+			g_ui32HotKeyFrame = psStream->ui32Current + 2;
+
+
+
+			g_bHotKeyPressed = IMG_TRUE;
+		}
+	}
+}
+
+IMG_VOID ActivateHotKeys(PDBG_STREAM psStream)
+{
+
+
+	ReadInHotKeys();
+
+
+
+	if (!g_PrivateHotKeyData.sHotKeyInfo.hHotKey)
+	{
+		if (g_PrivateHotKeyData.ui32ScanCode != 0)
+		{
+			PVR_DPF((PVR_DBG_MESSAGE,"Activate HotKey for PDUMP.\n"));
+
+
+
+			g_PrivateHotKeyData.sHotKeyInfo.pvStream = psStream;
+
+			DefineHotKey(g_PrivateHotKeyData.ui32ScanCode, g_PrivateHotKeyData.ui32ShiftState, &g_PrivateHotKeyData.sHotKeyInfo);
+		}
+		else
+		{
+			g_PrivateHotKeyData.sHotKeyInfo.hHotKey = 0;
+		}
+	}
+}
+
+IMG_VOID DeactivateHotKeys(IMG_VOID)
+{
+	if (g_PrivateHotKeyData.sHotKeyInfo.hHotKey != 0)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE,"Deactivate HotKey.\n"));
+
+		RemoveHotKey(g_PrivateHotKeyData.sHotKeyInfo.hHotKey);
+		g_PrivateHotKeyData.sHotKeyInfo.hHotKey = 0;
+	}
+}
+
+
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hotkey.h b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hotkey.h
new file mode 100644
index 0000000..5f95d22
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/hotkey.h
@@ -0,0 +1,56 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _HOTKEY_
+#define _HOTKEY_
+
+
+typedef struct _hotkeyinfo
+{
+	IMG_UINT8 ui8ScanCode;
+	IMG_UINT8 ui8Type;
+	IMG_UINT8 ui8Flag;
+	IMG_UINT8 ui8Filler1;
+	IMG_UINT32 ui32ShiftState;
+	IMG_UINT32 ui32HotKeyProc;
+	IMG_VOID *pvStream;
+	IMG_UINT32 hHotKey;
+} HOTKEYINFO, *PHOTKEYINFO;
+
+typedef struct _privatehotkeydata
+{
+	IMG_UINT32		ui32ScanCode;
+	IMG_UINT32		ui32ShiftState;
+	HOTKEYINFO	sHotKeyInfo;
+} PRIVATEHOTKEYDATA, *PPRIVATEHOTKEYDATA;
+
+
+IMG_VOID ReadInHotKeys (IMG_VOID);
+IMG_VOID ActivateHotKeys(PDBG_STREAM psStream);
+IMG_VOID DeactivateHotKeys(IMG_VOID);
+
+IMG_VOID RemoveHotKey (IMG_UINT32 hHotKey);
+IMG_VOID DefineHotKey (IMG_UINT32 ui32ScanCode, IMG_UINT32 ui32ShiftState, PHOTKEYINFO psInfo);
+IMG_VOID RegisterKeyPressed (IMG_UINT32 ui32ScanCode, PHOTKEYINFO psInfo);
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/ioctl.c b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/ioctl.c
new file mode 100644
index 0000000..6b130d7
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/ioctl.c
@@ -0,0 +1,367 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+
+
+#ifdef LINUX
+#include <asm/uaccess.h>
+#endif
+
+#include "img_types.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+
+
+IMG_UINT32 DBGDIOCDrivCreateStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	PDBG_IN_CREATESTREAM psIn;
+	IMG_VOID * *ppvOut;
+	#ifdef LINUX
+	static IMG_CHAR name[32];
+	#endif
+
+	psIn = (PDBG_IN_CREATESTREAM) pvInBuffer;
+	ppvOut = (IMG_VOID * *) pvOutBuffer;
+
+	#ifdef LINUX
+
+	if(copy_from_user(name, psIn->pszName, 32) != 0)
+	{
+		return IMG_FALSE;
+	}
+
+	*ppvOut = ExtDBGDrivCreateStream(name, psIn->ui32CapMode, psIn->ui32OutMode, 0, psIn->ui32Pages);
+
+	#else
+	*ppvOut = ExtDBGDrivCreateStream(psIn->pszName, psIn->ui32CapMode, psIn->ui32OutMode, DEBUG_FLAGS_NO_BUF_EXPANDSION, psIn->ui32Pages);
+	#endif
+
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivDestroyStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	IMG_UINT32 *		pStream;
+	PDBG_STREAM	psStream;
+
+	pStream = (IMG_UINT32 *) pvInBuffer;
+	psStream = (PDBG_STREAM) *pStream;
+
+	PVR_UNREFERENCED_PARAMETER(	pvOutBuffer);
+
+	ExtDBGDrivDestroyStream(psStream);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivGetStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	PDBG_IN_FINDSTREAM psParams;
+	IMG_UINT32 *	pui32Stream;
+
+	psParams		= (PDBG_IN_FINDSTREAM)pvInBuffer;
+	pui32Stream	= (IMG_UINT32 *)pvOutBuffer;
+
+	*pui32Stream = (IMG_UINT32)ExtDBGDrivFindStream(psParams->pszName, psParams->bResetStream);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWriteString(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	PDBG_IN_WRITESTRING psParams;
+	IMG_UINT32 *				pui32OutLen;
+
+	psParams = (PDBG_IN_WRITESTRING) pvInBuffer;
+	pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+	*pui32OutLen = ExtDBGDrivWriteString((PDBG_STREAM) psParams->pvStream,psParams->pszString,psParams->ui32Level);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWriteStringCM(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	PDBG_IN_WRITESTRING psParams;
+	IMG_UINT32 *				pui32OutLen;
+
+	psParams = (PDBG_IN_WRITESTRING) pvInBuffer;
+	pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+	*pui32OutLen = ExtDBGDrivWriteStringCM((PDBG_STREAM) psParams->pvStream,psParams->pszString,psParams->ui32Level);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivReadString(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	IMG_UINT32 *				pui32OutLen;
+	PDBG_IN_READSTRING	psParams;
+
+	psParams = (PDBG_IN_READSTRING) pvInBuffer;
+	pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+	*pui32OutLen = ExtDBGDrivReadString(psParams->pvStream,psParams->pszString,psParams->ui32StringLen);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWrite(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	IMG_UINT32 *				pui32BytesCopied;
+	PDBG_IN_WRITE		psInParams;
+
+	psInParams = (PDBG_IN_WRITE) pvInBuffer;
+	pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+	*pui32BytesCopied = ExtDBGDrivWrite((PDBG_STREAM) psInParams->pvStream,psInParams->pui8InBuffer,psInParams->ui32TransferSize,psInParams->ui32Level);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWrite2(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	IMG_UINT32 *				pui32BytesCopied;
+	PDBG_IN_WRITE		psInParams;
+
+	psInParams = (PDBG_IN_WRITE) pvInBuffer;
+	pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+	*pui32BytesCopied = ExtDBGDrivWrite2((PDBG_STREAM) psInParams->pvStream,psInParams->pui8InBuffer,psInParams->ui32TransferSize,psInParams->ui32Level);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWriteCM(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	IMG_UINT32 *				pui32BytesCopied;
+	PDBG_IN_WRITE		psInParams;
+
+	psInParams = (PDBG_IN_WRITE) pvInBuffer;
+	pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+	*pui32BytesCopied = ExtDBGDrivWriteCM((PDBG_STREAM) psInParams->pvStream,psInParams->pui8InBuffer,psInParams->ui32TransferSize,psInParams->ui32Level);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivRead(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	IMG_UINT32 *				pui32BytesCopied;
+	PDBG_IN_READ		psInParams;
+
+	psInParams = (PDBG_IN_READ) pvInBuffer;
+	pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+	*pui32BytesCopied = ExtDBGDrivRead((PDBG_STREAM) psInParams->pvStream,psInParams->bReadInitBuffer, psInParams->ui32OutBufferSize,psInParams->pui8OutBuffer);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivSetCaptureMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	PDBG_IN_SETDEBUGMODE 	psParams;
+
+	psParams = (PDBG_IN_SETDEBUGMODE) pvInBuffer;
+	PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+	ExtDBGDrivSetCaptureMode((PDBG_STREAM) psParams->pvStream,
+						  psParams->ui32Mode,
+						  psParams->ui32Start,
+						  psParams->ui32End,
+						  psParams->ui32SampleRate);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivSetOutMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	PDBG_IN_SETDEBUGOUTMODE psParams;
+
+	psParams = (PDBG_IN_SETDEBUGOUTMODE) pvInBuffer;
+	PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+	ExtDBGDrivSetOutputMode((PDBG_STREAM) psParams->pvStream,psParams->ui32Mode);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivSetDebugLevel(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	PDBG_IN_SETDEBUGLEVEL psParams;
+
+	psParams = (PDBG_IN_SETDEBUGLEVEL) pvInBuffer;
+	PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+	ExtDBGDrivSetDebugLevel((PDBG_STREAM) psParams->pvStream,psParams->ui32Level);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivSetFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	PDBG_IN_SETFRAME	psParams;
+
+	psParams = (PDBG_IN_SETFRAME) pvInBuffer;
+	PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+	ExtDBGDrivSetFrame((PDBG_STREAM) psParams->pvStream,psParams->ui32Frame);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivGetFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	IMG_UINT32 *		pStream;
+	PDBG_STREAM	psStream;
+	IMG_UINT32 *		pui32Current;
+
+	pStream = (IMG_UINT32 *) pvInBuffer;
+	psStream = (PDBG_STREAM) *pStream;
+	pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+	*pui32Current = ExtDBGDrivGetFrame(psStream);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivIsCaptureFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	PDBG_IN_ISCAPTUREFRAME psParams;
+	IMG_UINT32 *		pui32Current;
+
+	psParams = (PDBG_IN_ISCAPTUREFRAME) pvInBuffer;
+	pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+	*pui32Current = ExtDBGDrivIsCaptureFrame((PDBG_STREAM) psParams->pvStream, psParams->bCheckPreviousFrame);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivOverrideMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	PDBG_IN_OVERRIDEMODE	psParams;
+
+	psParams = (PDBG_IN_OVERRIDEMODE) pvInBuffer;
+	PVR_UNREFERENCED_PARAMETER(	pvOutBuffer);
+
+	ExtDBGDrivOverrideMode((PDBG_STREAM) psParams->pvStream,psParams->ui32Mode);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivDefaultMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	IMG_UINT32 *		pStream;
+	PDBG_STREAM	psStream;
+
+	pStream = (IMG_UINT32 *) pvInBuffer;
+	psStream = (PDBG_STREAM) *pStream;
+
+	PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+	ExtDBGDrivDefaultMode(psStream);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivSetMarker(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	PDBG_IN_SETMARKER	psParams;
+
+	psParams = (PDBG_IN_SETMARKER) pvInBuffer;
+	PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+	ExtDBGDrivSetMarker((PDBG_STREAM) psParams->pvStream, psParams->ui32Marker);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivGetMarker(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	IMG_UINT32 *		pStream;
+	PDBG_STREAM	psStream;
+	IMG_UINT32 *		pui32Current;
+
+	pStream = (IMG_UINT32 *) pvInBuffer;
+	psStream = (PDBG_STREAM) *pStream;
+	pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+	*pui32Current = ExtDBGDrivGetMarker(psStream);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivGetServiceTable(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	IMG_UINT32 *	pui32Out;
+
+	PVR_UNREFERENCED_PARAMETER(pvInBuffer);
+	pui32Out = (IMG_UINT32 *) pvOutBuffer;
+
+	*pui32Out = DBGDrivGetServiceTable();
+
+    return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWriteLF(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	PDBG_IN_WRITE_LF	psInParams;
+	IMG_UINT32 *				pui32BytesCopied;
+
+	psInParams = (PDBG_IN_WRITE_LF) pvInBuffer;
+	pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+	*pui32BytesCopied = ExtDBGDrivWriteLF(psInParams->pvStream,
+										psInParams->pui8InBuffer,
+										psInParams->ui32BufferSize,
+										psInParams->ui32Level,
+										psInParams->ui32Flags);
+
+	return IMG_TRUE;
+}
+
+IMG_UINT32 DBGDIOCDrivReadLF(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	IMG_UINT32 *				pui32BytesCopied;
+	PDBG_IN_READ		psInParams;
+
+	psInParams = (PDBG_IN_READ) pvInBuffer;
+	pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+	*pui32BytesCopied = ExtDBGDrivReadLF((PDBG_STREAM) psInParams->pvStream,psInParams->ui32OutBufferSize,psInParams->pui8OutBuffer);
+
+	return(IMG_TRUE);
+}
+
+IMG_UINT32 DBGDIOCDrivWaitForEvent(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+	DBG_EVENT eEvent = (DBG_EVENT)(*(IMG_UINT32 *)pvInBuffer);
+
+	PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+	ExtDBGDrivWaitForEvent(eEvent);
+
+	return(IMG_TRUE);
+}
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/ioctl.h b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/ioctl.h
new file mode 100644
index 0000000..882408c
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/common/ioctl.h
@@ -0,0 +1,83 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#ifndef _IOCTL_
+#define _IOCTL_
+
+
+IMG_UINT32 DBGDIOCDrivCreateStream(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivDestroyStream(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivGetStream(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWriteString(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivReadString(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWrite(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWrite2(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivRead(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivSetCaptureMode(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivSetOutMode(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivSetDebugLevel(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivSetFrame(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivGetFrame(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivOverrideMode(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivDefaultMode(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivGetServiceTable(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWriteStringCM(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWriteCM(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivSetMarker(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivGetMarker(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivIsCaptureFrame(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWriteLF(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivReadLF(IMG_VOID *, IMG_VOID *);
+IMG_UINT32 DBGDIOCDrivWaitForEvent(IMG_VOID*, IMG_VOID *);
+
+IMG_UINT32 (*g_DBGDrivProc[])(IMG_VOID *, IMG_VOID *) =
+{
+	DBGDIOCDrivCreateStream,
+	DBGDIOCDrivDestroyStream,
+	DBGDIOCDrivGetStream,
+	DBGDIOCDrivWriteString,
+	DBGDIOCDrivReadString,
+	DBGDIOCDrivWrite,
+	DBGDIOCDrivRead,
+	DBGDIOCDrivSetCaptureMode,
+	DBGDIOCDrivSetOutMode,
+	DBGDIOCDrivSetDebugLevel,
+	DBGDIOCDrivSetFrame,
+	DBGDIOCDrivGetFrame,
+	DBGDIOCDrivOverrideMode,
+	DBGDIOCDrivDefaultMode,
+	DBGDIOCDrivGetServiceTable,
+	DBGDIOCDrivWrite2,
+	DBGDIOCDrivWriteStringCM,
+	DBGDIOCDrivWriteCM,
+	DBGDIOCDrivSetMarker,
+	DBGDIOCDrivGetMarker,
+	DBGDIOCDrivIsCaptureFrame,
+	DBGDIOCDrivWriteLF,
+	DBGDIOCDrivReadLF,
+	DBGDIOCDrivWaitForEvent
+};
+
+#define MAX_DBGVXD_W32_API (sizeof(g_DBGDrivProc)/sizeof(IMG_UINT32))
+
+#endif
+
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/hostfunc.c b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/hostfunc.c
new file mode 100644
index 0000000..29c3427
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/hostfunc.c
@@ -0,0 +1,300 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <asm/page.h>
+#include <linux/vmalloc.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/mutex.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#include <linux/hardirq.h>
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#endif
+
+#include <linux/slab.h>
+
+#include "img_types.h"
+#include "pvr_debug.h"
+
+#include "dbgdrvif.h"
+#include "dbgdriv/common/hostfunc.h"
+
+#if !defined(SUPPORT_DRI_DRM)
+IMG_UINT32	gPVRDebugLevel = DBGPRIV_WARNING;
+
+#define PVR_STRING_TERMINATOR		'\0'
+#define PVR_IS_FILE_SEPARATOR(character) ( ((character) == '\\') || ((character) == '/') )
+
+void PVRSRVDebugPrintf	(
+						IMG_UINT32	ui32DebugLevel,
+						const IMG_CHAR*	pszFileName,
+						IMG_UINT32	ui32Line,
+						const IMG_CHAR*	pszFormat,
+						...
+					)
+{
+	IMG_BOOL bTrace, bDebug;
+#if !defined(__sh__)
+	IMG_CHAR *pszLeafName;
+
+	pszLeafName = (char *)strrchr (pszFileName, '\\');
+
+	if (pszLeafName)
+	{
+		pszFileName = pszLeafName;
+	}
+#endif
+
+	bTrace = gPVRDebugLevel & ui32DebugLevel & DBGPRIV_CALLTRACE;
+	bDebug = ((gPVRDebugLevel & DBGPRIV_ALLLEVELS) >= ui32DebugLevel);
+
+	if (bTrace || bDebug)
+	{
+		va_list vaArgs;
+		static char szBuffer[256];
+
+		va_start (vaArgs, pszFormat);
+
+
+		if (bDebug)
+		{
+			switch(ui32DebugLevel)
+			{
+				case DBGPRIV_FATAL:
+				{
+					strcpy (szBuffer, "PVR_K:(Fatal): ");
+					break;
+				}
+				case DBGPRIV_ERROR:
+				{
+					strcpy (szBuffer, "PVR_K:(Error): ");
+					break;
+				}
+				case DBGPRIV_WARNING:
+				{
+					strcpy (szBuffer, "PVR_K:(Warning): ");
+					break;
+				}
+				case DBGPRIV_MESSAGE:
+				{
+					strcpy (szBuffer, "PVR_K:(Message): ");
+					break;
+				}
+				case DBGPRIV_VERBOSE:
+				{
+					strcpy (szBuffer, "PVR_K:(Verbose): ");
+					break;
+				}
+				default:
+				{
+					strcpy (szBuffer, "PVR_K:(Unknown message level)");
+					break;
+				}
+			}
+		}
+		else
+		{
+			strcpy (szBuffer, "PVR_K: ");
+		}
+
+		vsprintf (&szBuffer[strlen(szBuffer)], pszFormat, vaArgs);
+
+
+
+		if (!bTrace)
+		{
+			sprintf (&szBuffer[strlen(szBuffer)], " [%d, %s]", (int)ui32Line, pszFileName);
+		}
+
+		printk(KERN_INFO "%s\r\n", szBuffer);
+
+		va_end (vaArgs);
+	}
+}
+#endif
+
+IMG_VOID HostMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
+{
+	memset(pvDest, (int) ui8Value, (size_t) ui32Size);
+}
+
+IMG_VOID HostMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMCPY)
+    unsigned char *src,*dst;
+    int i;
+
+    src=(unsigned char *)pvSrc;
+    dst=(unsigned char *)pvDst;
+    for(i=0;i<ui32Size;i++)
+    {
+        dst[i]=src[i];
+    }
+#else
+    memcpy(pvDst, pvSrc, ui32Size);
+#endif
+}
+
+IMG_UINT32 HostReadRegistryDWORDFromString(char *pcKey, char *pcValueName, IMG_UINT32 *pui32Data)
+{
+
+	return 0;
+}
+
+IMG_VOID * HostPageablePageAlloc(IMG_UINT32 ui32Pages)
+{
+    return (void*)vmalloc(ui32Pages * PAGE_SIZE);
+}
+
+IMG_VOID HostPageablePageFree(IMG_VOID * pvBase)
+{
+    vfree(pvBase);
+}
+
+IMG_VOID * HostNonPageablePageAlloc(IMG_UINT32 ui32Pages)
+{
+    return (void*)vmalloc(ui32Pages * PAGE_SIZE);
+}
+
+IMG_VOID HostNonPageablePageFree(IMG_VOID * pvBase)
+{
+    vfree(pvBase);
+}
+
+IMG_VOID * HostMapKrnBufIntoUser(IMG_VOID * pvKrnAddr, IMG_UINT32 ui32Size, IMG_VOID **ppvMdl)
+{
+
+	return IMG_NULL;
+}
+
+IMG_VOID HostUnMapKrnBufFromUser(IMG_VOID * pvUserAddr, IMG_VOID * pvMdl, IMG_VOID * pvProcess)
+{
+
+}
+
+IMG_VOID HostCreateRegDeclStreams(IMG_VOID)
+{
+
+}
+
+IMG_VOID * HostCreateMutex(IMG_VOID)
+{
+	struct semaphore *psSem;
+
+	psSem = kmalloc(sizeof(*psSem), GFP_KERNEL);
+	if (psSem)
+	{
+		init_MUTEX(psSem);
+	}
+
+	return psSem;
+}
+
+IMG_VOID HostAquireMutex(IMG_VOID * pvMutex)
+{
+	BUG_ON(in_interrupt());
+
+#if defined(PVR_DEBUG_DBGDRV_DETECT_HOST_MUTEX_COLLISIONS)
+	if (down_trylock((struct semaphore *)pvMutex))
+	{
+		printk(KERN_INFO "HostAquireMutex: Waiting for mutex\n");
+		down((struct semaphore *)pvMutex);
+	}
+#else
+	down((struct semaphore *)pvMutex);
+#endif
+}
+
+IMG_VOID HostReleaseMutex(IMG_VOID * pvMutex)
+{
+	up((struct semaphore *)pvMutex);
+}
+
+IMG_VOID HostDestroyMutex(IMG_VOID * pvMutex)
+{
+	if (pvMutex)
+	{
+		kfree(pvMutex);
+	}
+}
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+
+#define	EVENT_WAIT_TIMEOUT_MS	500
+#define	EVENT_WAIT_TIMEOUT_JIFFIES	(EVENT_WAIT_TIMEOUT_MS * HZ / 1000)
+
+static int iStreamData;
+static wait_queue_head_t sStreamDataEvent;
+
+IMG_INT32 HostCreateEventObjects(IMG_VOID)
+{
+	init_waitqueue_head(&sStreamDataEvent);
+
+	return 0;
+}
+
+IMG_VOID HostWaitForEvent(DBG_EVENT eEvent)
+{
+	switch(eEvent)
+	{
+		case DBG_EVENT_STREAM_DATA:
+
+			wait_event_interruptible_timeout(sStreamDataEvent, iStreamData != 0, EVENT_WAIT_TIMEOUT_JIFFIES);
+			iStreamData = 0;
+			break;
+		default:
+
+			msleep_interruptible(EVENT_WAIT_TIMEOUT_MS);
+			break;
+	}
+}
+
+IMG_VOID HostSignalEvent(DBG_EVENT eEvent)
+{
+	switch(eEvent)
+	{
+		case DBG_EVENT_STREAM_DATA:
+			iStreamData = 1;
+			wake_up_interruptible(&sStreamDataEvent);
+			break;
+		default:
+			break;
+	}
+}
+
+IMG_VOID HostDestroyEventObjects(IMG_VOID)
+{
+}
+#endif
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/kbuild/Makefile b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/kbuild/Makefile
new file mode 100644
index 0000000..44c1357
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/kbuild/Makefile
@@ -0,0 +1,33 @@
+#
+# Copyright (c) Imagination Technologies Ltd.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE. 
+# 
+#
+#
+
+include $(EURASIAROOT)/eurasiacon/build/linux/kbuild/Makefile.kbuild_subdir_common
+
+MODULE		= dbgdrv
+
+INCLUDES =
+
+SOURCES	=
+				
+include $(EURASIAROOT)/tools/intern/debug/dbgdriv/linux/makefile.linux.common
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/main.c b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/main.c
new file mode 100644
index 0000000..08691c0
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/main.c
@@ -0,0 +1,294 @@
+/**********************************************************************
+ Copyright (c) Imagination Technologies Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ ******************************************************************************/
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/version.h>
+
+#if defined(LDM_PLATFORM) && !defined(SUPPORT_DRI_DRM)
+#include <linux/platform_device.h>
+#endif
+
+#if defined(LDM_PCI) && !defined(SUPPORT_DRI_DRM)
+#include <linux/pci.h>
+#endif
+
+#include <asm/uaccess.h>
+
+#if defined(SUPPORT_DRI_DRM)
+#include "drmP.h"
+#include "drm.h"
+#endif
+
+#include "img_types.h"
+#include "client/linuxsrv.h"
+#include "dbgdriv/common/ioctl.h"
+#include "dbgdrvif.h"
+#include "dbgdriv/common/dbgdriv.h"
+#include "dbgdriv/common/hostfunc.h"
+#include "pvr_debug.h"
+#include "pvrmodule.h"
+
+#if defined(SUPPORT_DRI_DRM)
+
+#include "pvr_drm_shared.h"
+#include "pvr_drm.h"
+
+#else
+
+#define DRVNAME "dbgdrv"
+MODULE_SUPPORTED_DEVICE(DRVNAME);
+
+#if (defined(LDM_PLATFORM) || defined(LDM_PCI)) && !defined(SUPPORT_DRI_DRM)
+static struct class *psDbgDrvClass;
+#endif
+
+static int AssignedMajorNumber = 0;
+
+long dbgdrv_ioctl(struct file *, unsigned int, unsigned long);
+
+static int dbgdrv_open(struct inode unref__ * pInode, struct file unref__ * pFile)
+{
+	return 0;
+}
+
+static int dbgdrv_release(struct inode unref__ * pInode, struct file unref__ * pFile)
+{
+	return 0;
+}
+
+static int dbgdrv_mmap(struct file* pFile, struct vm_area_struct* ps_vma)
+{
+	return 0;
+}
+
+static struct file_operations dbgdrv_fops = {
+	.owner          = THIS_MODULE,
+	.unlocked_ioctl = dbgdrv_ioctl,
+	.open           = dbgdrv_open,
+	.release        = dbgdrv_release,
+	.mmap           = dbgdrv_mmap,
+};
+
+#endif
+
+void DBGDrvGetServiceTable(void **fn_table)
+{
+	extern DBGKM_SERVICE_TABLE g_sDBGKMServices;
+
+	*fn_table = &g_sDBGKMServices;
+}
+
+#if defined(SUPPORT_DRI_DRM)
+void dbgdrv_cleanup(void)
+#else
+void cleanup_module(void)
+#endif
+{
+#if !defined(SUPPORT_DRI_DRM)
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+	device_destroy(psDbgDrvClass, MKDEV(AssignedMajorNumber, 0));
+	class_destroy(psDbgDrvClass);
+#endif
+	unregister_chrdev(AssignedMajorNumber, DRVNAME);
+#endif
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+	HostDestroyEventObjects();
+#endif
+	HostDestroyMutex(g_pvAPIMutex);
+	return;
+}
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT dbgdrv_init(void)
+#else
+int init_module(void)
+#endif
+{
+#if (defined(LDM_PLATFORM) || defined(LDM_PCI)) && !defined(SUPPORT_DRI_DRM)
+	struct device *psDev;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+	int err = -EBUSY;
+#endif
+
+
+	if ((g_pvAPIMutex=HostCreateMutex()) == IMG_NULL)
+	{
+		return -ENOMEM;
+	}
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+
+	(void) HostCreateEventObjects();
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+	AssignedMajorNumber =
+	register_chrdev(AssignedMajorNumber, DRVNAME, &dbgdrv_fops);
+
+	if (AssignedMajorNumber <= 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR," unable to get major\n"));
+		goto ErrDestroyEventObjects;
+	}
+
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+
+	psDbgDrvClass = class_create(THIS_MODULE, DRVNAME);
+	if (IS_ERR(psDbgDrvClass))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: unable to create class (%ld)",
+				 __func__, PTR_ERR(psDbgDrvClass)));
+		goto ErrUnregisterCharDev;
+	}
+
+	psDev = device_create(psDbgDrvClass, NULL, MKDEV(AssignedMajorNumber, 0),
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
+						  NULL,
+#endif
+						  DRVNAME);
+	if (IS_ERR(psDev))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: unable to create device (%ld)",
+								__func__, PTR_ERR(psDev)));
+		goto ErrDestroyClass;
+	}
+#endif
+#endif
+
+	return 0;
+
+#if !defined(SUPPORT_DRI_DRM)
+ErrDestroyEventObjects:
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+	HostDestroyEventObjects();
+#endif
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ErrUnregisterCharDev:
+	unregister_chrdev(AssignedMajorNumber, DRVNAME);
+ErrDestroyClass:
+	class_destroy(psDbgDrvClass);
+#endif
+	return err;
+#endif
+}
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT dbgdrv_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+#else
+long dbgdrv_ioctl(struct file *file, unsigned int ioctlCmd, unsigned long arg)
+#endif
+{
+	IOCTL_PACKAGE *pIP = (IOCTL_PACKAGE *) arg;
+	char *buffer, *in, *out;
+	unsigned int cmd;
+
+	if((pIP->ui32InBufferSize > (PAGE_SIZE >> 1) ) || (pIP->ui32OutBufferSize > (PAGE_SIZE >> 1)))
+	{
+		PVR_DPF((PVR_DBG_ERROR,"Sizes of the buffers are too large, cannot do ioctl\n"));
+		return -1;
+	}
+
+	buffer = (char *) HostPageablePageAlloc(1);
+	if(!buffer)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"Failed to allocate buffer, cannot do ioctl\n"));
+		return -EFAULT;
+	}
+
+	in = buffer;
+	out = buffer + (PAGE_SIZE >>1);
+
+	if(copy_from_user(in, pIP->pInBuffer, pIP->ui32InBufferSize) != 0)
+	{
+		goto init_failed;
+	}
+
+	cmd = ((pIP->ui32Cmd >> 2) & 0xFFF) - 0x801;
+
+	if(pIP->ui32Cmd == DEBUG_SERVICE_READ)
+	{
+		IMG_CHAR *ui8Tmp;
+		IMG_UINT32 *pui32BytesCopied = (IMG_UINT32 *)out;
+		DBG_IN_READ *psReadInParams = (DBG_IN_READ *)in;
+
+		ui8Tmp = vmalloc(psReadInParams->ui32OutBufferSize);
+
+		if(!ui8Tmp)
+		{
+			goto init_failed;
+		}
+
+		*pui32BytesCopied = ExtDBGDrivRead((DBG_STREAM *)psReadInParams->pvStream,
+										   psReadInParams->bReadInitBuffer,
+										   psReadInParams->ui32OutBufferSize,
+										   ui8Tmp);
+
+		if(copy_to_user(psReadInParams->pui8OutBuffer,
+						ui8Tmp,
+						*pui32BytesCopied) != 0)
+		{
+			vfree(ui8Tmp);
+			goto init_failed;
+		}
+
+		vfree(ui8Tmp);
+	}
+	else
+	{
+		(g_DBGDrivProc[cmd])(in, out);
+	}
+
+	if(copy_to_user(pIP->pOutBuffer, out, pIP->ui32OutBufferSize) != 0)
+	{
+		goto init_failed;
+	}
+
+	HostPageablePageFree((IMG_VOID *)buffer);
+	return 0;
+
+init_failed:
+	HostPageablePageFree((IMG_VOID *)buffer);
+	return -EFAULT;
+}
+
+
+void RemoveHotKey(unsigned hHotKey)
+{
+
+}
+
+void DefineHotKey(unsigned ScanCode, unsigned ShiftState, void *pInfo)
+{
+
+}
+
+EXPORT_SYMBOL(DBGDrvGetServiceTable);
diff --git a/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/makefile.linux.common b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/makefile.linux.common
new file mode 100644
index 0000000..f9a1c7f
--- /dev/null
+++ b/drivers/gpu/drm/emgd/pvr/tools/intern/debug/dbgdriv/linux/makefile.linux.common
@@ -0,0 +1,38 @@
+#
+# Copyright (c) Imagination Technologies Ltd.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE. 
+# 
+#
+#
+
+ifeq ($(SUPPORT_DRI_DRM),1)
+DBGDRV_SOURCES_ROOT = $(KBUILDROOT)/../tools/intern/debug/dbgdriv
+else
+DBGDRV_SOURCES_ROOT = ../..
+endif
+
+INCLUDES += 	-I$(EURASIAROOT)/include4 \
+			-I$(EURASIAROOT)/tools/intern/debug
+
+SOURCES	+=	$(DBGDRV_SOURCES_ROOT)/linux/main.c \
+				$(DBGDRV_SOURCES_ROOT)/common/dbgdriv.c \
+				$(DBGDRV_SOURCES_ROOT)/common/ioctl.c \
+				$(DBGDRV_SOURCES_ROOT)/linux/hostfunc.c \
+				$(DBGDRV_SOURCES_ROOT)/common/hotkey.c
-- 
1.7.3.4




More information about the yocto mailing list